?MZ? ?? ? @ ? o ¡ä ¨ª!?L¨ª!This program cannot be run in DOS mode. $ 3B¡ä¡ä¡Â#¨²?¡Â#¨²?¡Â#¨²?¡¡é??A#¨²?¡¡éT??#¨²?¡¡é¨´??#¨²??£¤'??#¨²??£¤¨´?t#¨²??£¤T??#¨²??£¤???#¨²?¡¡é??e#¨²?¡Â#??{#¨²?s£¤T??#¨²?s£¤???#¨²?Rich¡Â#¨²? PE d? ??g e " * o €? @ P ¨º¡é? `¨¢€? ¨ª P ? ?? ` # @ t P¨¢ ¨¤ @ D .text 1 o `.rdata j+ D , ? @ @.data PS ¨º @ ¨¤.pdata # ` $ ? @ @.fptable ? @ ¨¤.rsrc ?? ? ? @ @.reloc t @ ? /** * Front to the WordPress application. This file doesn't do anything, but loads home/eticmes/www/wp-content/plugins/quotes-llama/class-quotesllama.php 0000644 00000226124 15156140771 0022315 0 ustar 00 msg = ''; $this->plugin_options = get_option( 'quotes-llama-settings' ); $this->icons_url = $upload_dir['baseurl'] . '/quotes-llama/'; $this->icons_dir = $upload_dir['basedir'] . '/quotes-llama/'; // Create plugin database table. register_activation_hook( __FILE__, array( $this, 'db_setup' ) ); // Create plugin options. register_activation_hook( __FILE__, array( $this, 'activation' ) ); // Remove plugin options and settings when deactivating. register_deactivation_hook( __FILE__, array( $this, 'deactivation' ) ); } /** * Load backend. * * @since 3.0.0 * @access public */ public function admin_load() { if ( ! class_exists( 'QuotesLlama_Admin' ) ) { require_once 'includes/classes/class-quotesllama-admin.php'; } $ql_admin = new QuotesLlama_Admin(); $ql_admin->page_fields(); // Message for display in back-end. $ql_admin->msg = $this->msg; } /** * Register options array when activating plugin. * * @since 1.0.0 * @access public */ public function activation() { // Options default values. $add_options = array( 'show_page_author' => true, 'show_page_source' => true, 'show_page_image' => true, 'show_page_next' => false, 'show_gallery_author' => true, 'show_gallery_source' => true, 'show_gallery_image' => true, 'gallery_timer_show' => true, 'gallery_timer_interval' => '12', 'gallery_timer_minimum' => 10, 'sidebar' => 'left', 'background_color' => '#444', 'foreground_color' => 'silver', 'default_sort' => 'quote_id', 'default_order' => 'dsc', 'permission_level' => 'create_users', 'admin_reset' => true, 'export_delimiter' => '|', 'character_limit' => 0, 'next_quote_text' => '… (next quote)', 'ellipses_text' => '...', 'source_newline' => 'br', 'read_more_text' => '»', 'read_less_text' => '«', 'show_icons' => true, 'author_icon' => 'edit', 'source_icon' => 'migrate', 'search_allow' => false, 'http_display' => false, 'border_radius' => false, 'image_at_top' => false, 'align_quote' => 'left', 'transition_speed' => 1000, ); add_option( 'quotes-llama-settings', $add_options ); } /** * Allowed html lists. * * @since 1.1.2 * @access public * * @param string $type - Which set of allowed tags. * * @return array - Allowed html entities. */ public function allowed_html( $type ) { if ( 'style' === $type ) { $allowed_html = array( 'a' => array( 'href' => true, 'title' => true, 'target' => true, 'class' => true, 'rel' => true, ), 'img' => array( 'alt' => true, 'src' => true, ), 'br' => array( 'clear' => true, ), 'b' => array(), 'del' => array(), 'mark' => array(), 'strong' => array(), 'small' => array(), 'em' => array(), 'i' => array(), 'sub' => array(), 'sup' => array(), 'u' => array(), ); return $allowed_html; } if ( 'image' === $type ) { $allowed_html = array( 'img' => array( 'alt' => true, 'width' => true, 'title' => true, 'src' => true, ), ); return $allowed_html; } if ( 'column' === $type ) { $allowed_html = array( 'a' => array( 'href' => true, 'title' => true, 'target' => true, 'rel' => true, 'onclick' => true, ), 'div' => array( 'class' => true, ), 'th' => array( 'id' => true, 'class' => true, 'scope' => true, 'style' => true, ), 'img' => array( 'alt' => true, 'width' => true, 'title' => true, 'src' => true, ), 'label' => array( 'for' => true, 'class' => true, ), 'input' => array( 'type' => true, 'name' => true, 'value' => true, ), 'span' => array( 'class' => true, ), 'br' => array( 'clear' => true, ), 'b' => array(), 'del' => array(), 'mark' => array(), 'strong' => array(), 'small' => array(), 'em' => array(), 'i' => array(), 'sub' => array(), 'sup' => array(), 'u' => array(), ); return $allowed_html; } if ( 'div' === $type ) { $allowed_html = array( 'div' => array( 'class' => true, ), ); return $allowed_html; } if ( 'span' === $type ) { $allowed_html = array( 'span' => array( 'class' => true, ), ); return $allowed_html; } if ( 'option' === $type ) { $allowed_html = array( 'option' => array( 'value' => true, 'selected' => true, 'disabled' => true, 'hidden' => true, ), ); return $allowed_html; } if ( 'qform' === $type ) { $allowed_html = array( 'p' => array( 'class' => true, ), 'a' => array( 'href' => true, ), 'br' => array(), 'span' => array( 'class' => true, ), 'fieldset' => array( 'class' => true, ), 'legend' => array(), 'ul' => array( 'id' => true, ), 'li' => array(), 'table' => array( 'class' => true, 'cellpadding' => true, 'cellspacing' => true, 'width' => true, ), 'tbody' => array(), 'tr' => array( 'class' => true, ), 'th' => array( 'style' => true, 'scope' => true, 'valign' => true, 'label' => true, ), 'td' => array( 'style' => true, 'name' => true, 'textarea' => true, 'rows' => true, 'cols' => true, 'id' => true, ), 'textarea' => array( 'id' => true, 'name' => true, 'style' => true, 'rows' => true, 'cols' => true, ), 'form' => array( 'name' => true, 'method' => true, 'action' => true, ), 'label' => array( 'for' => true, ), 'input' => array( 'type' => true, 'name' => true, 'value' => true, 'class' => true, 'placeholder' => true, 'size' => true, 'id' => true, 'list' => true, 'checked' => true, ), 'button' => array( 'class' => true, 'input' => true, 'type' => true, 'id' => true, 'name' => true, ), 'img' => array( 'src' => true, 'alt' => true, ), 'option' => array( 'value' => true, 'selected' => true, 'disabled' => true, 'hidden' => true, ), 'select' => array( 'id' => true, 'name' => true, 'multiple' => true, 'size' => true, ), ); return $allowed_html; } if ( 'quote' === $type ) { $allowed_html = array( 'a' => array( 'href' => true, 'title' => true, 'class' => true, 'rel' => true, ), 'div' => array( 'class' => true, 'style' => true, ), 'input' => array( 'class' => true, 'type' => true, 'value' => true, ), 'img' => array( 'src' => true, 'id' => true, 'hspace' => true, 'align' => true, ), 'br' => array( 'clear' => true, ), 'hr' => array(), ); return $allowed_html; } if ( 'paginate' === $type ) { $allowed_html = array( 'a' => array( 'href' => true, 'title' => true, 'class' => true, ), 'div' => array( 'class' => true, ), 'span' => array( 'class' => true, ), 'input' => array( 'class' => true, 'id' => true, 'title' => true, 'type' => true, 'name' => true, 'value' => true, 'size' => true, ), 'label' => array( 'for' => true, 'class' => true, ), ); return $allowed_html; } if ( 'print' === $type ) { $allowed_html = array( 'a' => array( 'href' => true, 'title' => true, 'class' => true, ), 'div' => array( 'class' => true, ), 'th' => array( 'id' => true, 'class' => true, 'scope' => true, 'style' => true, ), 'label' => array( 'for' => true, 'class' => true, ), 'input' => array( 'class' => true, 'id' => true, 'title' => true, 'type' => true, 'scope' => true, 'style' => true, 'checkbox' => true, ), ); return $allowed_html; } } /** * $_POST Delete/Rename a category. * * @since 3.0.0 * @access public */ public function category_delete_rename() { // Nonce. $nonce = isset( $_POST['quotes_llama_admin_tabs'] ) ? sanitize_text_field( wp_unslash( $_POST['quotes_llama_admin_tabs'] ) ) : ''; // New category name. $category = isset( $_POST['ql-bulk-category'] ) ? sanitize_text_field( wp_unslash( $_POST['ql-bulk-category'] ) ) : ''; // Category to be renamed. $cat_old = isset( $_POST['ql-bulk-category-old'] ) ? sanitize_text_field( wp_unslash( $_POST['ql-bulk-category-old'] ) ) : ''; if ( wp_verify_nonce( $nonce, 'quotes_llama_admin_tabs' ) ) { if ( isset( $_POST['ql-delete-cat-btn'] ) ) { if ( ! empty( $category ) ) { $this->msg = $this->category_delete_rename_actions( $category, 'delete' ); } else { $this->msg = $this->message( esc_html__( 'Transaction failed: Select an existing category for deletion.', 'quotes-llama' ), 'nay' ); } } if ( isset( $_POST['ql-rename-cat-btn'] ) ) { if ( ! empty( $cat_old ) ) { $this->msg = $this->category_delete_rename_actions( $category, 'rename', $cat_old ); } else { $this->msg = $this->message( esc_html__( 'Transaction failed: Select an existing category to rename.', 'quotes-llama' ), 'nay' ); } } } } /** * Category bulk actions - Delete/Rename a category. * * @since 2.0.5 * @access private * * @param string $category - Category. * @param string $mode - Delete or rename. * @param string $cat_old - Old category. * * @return string - Message of success or failure. */ private function category_delete_rename_actions( $category, $mode, $cat_old = null ) { global $wpdb; // Bool result of query. $result = false; // Count of all result. $results = 0; // Categories list to delete. if ( 'delete' === $mode ) { $like = '%' . $wpdb->esc_like( $category ) . '%'; } // Categories list to rename. if ( 'rename' === $mode ) { $like = '%' . $wpdb->esc_like( $cat_old ) . '%'; } $cats = $wpdb->get_results( // phpcs:ignore $wpdb->prepare( 'SELECT quote_id, category FROM ' . $wpdb->prefix . 'quotes_llama' . ' WHERE category LIKE %s', // phpcs:ignore $like ) ); // Unset/Replace category from each quote that it exists in. if ( isset( $cats ) ) { foreach ( $cats as $categ ) { // Turn .csv string into array. $categories = explode( ', ', $categ->category ); // If deleting category. if ( 'delete' === $mode ) { $cat = array_search( $category, $categories, true ); // Unset instance if exists. if ( false !== $cat ) { unset( $categories[ $cat ] ); } } // If renaming category. if ( 'rename' === $mode ) { $cat = array_search( $cat_old, $categories, true ); // Replace instance if exists. if ( false !== $cat ) { $categories[ $cat ] = $category; } } // Turn array back into .csv string. $new_cats = implode( ', ', $categories ); // Update. $result = $wpdb->update( // phpcs:ignore $wpdb->prefix . 'quotes_llama', array( 'category' => $new_cats ), array( 'quote_id' => $categ->quote_id ), '%s', '%d' ); // Update results count. $results = $results + $result; } } if ( false === $result ) { return $this->message( esc_html__( 'Transaction failed:', 'quotes-llama' ) . ' ' . $mode . ' of ' . $results . ' records (' . $category . ') - ' . $results, 'nay' ); } else { return $this->message( esc_html__( 'Transaction completed:', 'quotes-llama' ) . ' ' . $mode . ' of ' . $results . ' records (' . $category . ')', 'yay' ); } } /** * Check if an option isset. * * @since 1.0.0 * @access public * * @param string $option - the option to check on. * * @return mixed - false if no option or option string if found. */ public function check_option( $option ) { if ( ! $option ) { return false; } if ( isset( $this->plugin_options[ "$option" ] ) ) { return $this->plugin_options[ "$option" ]; } else { return false; } } /** * Converts plaintext URI to HTML links. * Edit copy of make_clickable funcion from /includes/formatting.php. * * Converts URI, www and ftp, and email addresses. Finishes by fixing links * within links. * * @since 1.1.1 * @access public * * @param string $text Content to convert URIs. * * @return string Content with converted URIs. */ public function clickable( $text ) { // Return string. $r = ''; // Split out HTML tags. $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // Keep track of how many levels link is nested inside
or .
$nested_code_pre = 0;
// Process text links.
foreach ( $textarr as $piece ) {
if ( preg_match( '|^]|i', $piece ) ||
preg_match( '|^]|i', $piece ) ||
preg_match( '|^' === strtolower( $piece ) ||
'' === strtolower( $piece ) ) ) {
$nested_code_pre--;
}
if ( $nested_code_pre ||
empty( $piece ) ||
( '<' === $piece[0] && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) {
$r .= $piece;
continue;
}
// Long strings might contain expensive edge cases...
if ( 10000 < strlen( $piece ) ) {
// 2100: Extra room for scheme and leading and trailing parenthesis.
foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) {
if ( 2101 < strlen( $chunk ) ) { // Too big.
$r .= $chunk;
} else {
$r .= clickable( $chunk );
}
}
} else {
// Pad with whitespace to simplify the regexes.
$ret = " $piece ";
$url_clickable = '~
([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation.
( # 2: URL.
[\\w]{1,20}+:// # Scheme and hier-part prefix.
(?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long.
[\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character.
(?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character.
[\'.,;:!?)] # Punctuation URL character.
[\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character.
)*
)
(\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing).
~xS';
// The regex is a non-anchored pattern and does not have a single fixed starting character.
$ret = preg_replace_callback( $url_clickable, array( $this, 'make_url_clickable_callback' ), $ret ); // Creates links of http and https.
$ret = preg_replace( "#(^|[\n ])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1\\2", $ret ); // Creates link of www.
// Display www in links if enabled. Remove whitespace padding.
if ( $this->check_option( 'http_display' ) ) {
$ret = substr( $ret, 1, -1 );
$r .= $ret;
} else {
$ret = str_replace( 'www.', '', $ret );
$ret = substr( $ret, 1, -1 );
$r .= $ret;
}
}
}
$r = preg_replace( '#(]+?>|>))]+?>([^>]+?)#i', '$1$3', $r ); // Cleanup of accidental links within links.
return $this->close_tags( $r );
}
/**
* Count html tags and provide closing tag if missing.
* This does not close inline but at the end of the element.
* You will still see bleed out but not into the rest of the content.
*
* @since 1.1.2
* @access private
*
* @param string $html - String to check.
* @return string - String with closing tags matched.
*/
private function close_tags( $html ) {
// Put all opened tags into an array.
preg_match_all( '#<([a-z]+)(?: .*)?(?#iU', $html, $result );
// Put all closed tags into an array.
$openedtags = $result[1];
preg_match_all( '#([a-z]+)>#iU', $html, $result );
$closedtags = $result[1];
$len_opened = count( $openedtags );
if ( count( $closedtags ) === $len_opened ) {
return $html;
}
// Reverse array elements.
$openedtags = array_reverse( $openedtags );
for ( $i = 0; $i < $len_opened; $i++ ) {
// If no close tag.
if ( ! in_array( $openedtags[ $i ], $closedtags, true ) ) {
$html .= '' . $openedtags[ $i ] . '>'; // Make one.
} else {
// Close tag found, so remove from list.
unset( $closedtags[ array_search( $openedtags[ $i ], $closedtags, true ) ] );
}
}
return $html;
}
/**
* Conditional css enqueues.
*
* @since 2.1.2
* @access public
*/
public function css_conditionals() {
// CSS if image should be centered at top.
if ( isset( $this->plugin_options['image_at_top'] ) ) {
wp_enqueue_style( 'quotes-llama-css-image-center' );
}
// CSS if image should be round.
if ( isset( $this->plugin_options['border_radius'] ) ) {
wp_enqueue_style( 'quotes-llama-css-image-round' );
}
// CSS for quote alignment.
if ( isset( $this->plugin_options['align_quote'] ) ) {
if ( 'center' === $this->plugin_options['align_quote'] ) {
wp_enqueue_style( 'quotes-llama-css-quote-center' );
} elseif ( 'left' === $this->plugin_options['align_quote'] ) {
wp_enqueue_style( 'quotes-llama-css-quote-left' );
} elseif ( 'right' === $this->plugin_options['align_quote'] ) {
wp_enqueue_style( 'quotes-llama-css-quote-right' );
}
}
// CSS to reformat icon images.
wp_enqueue_style( 'quotes-llama-css-icons-format' );
}
/**
* Remove api setting when deactivating plugin and the options but, only if enabled in options.
*
* @since 1.0.0
* @access public
*/
public function deactivation() {
if ( isset( $this->plugin_options['admin_reset'] ) ) {
delete_option( 'quotes-llama-settings' );
}
unregister_setting( 'quotes-llama-settings', 'quotes-llama-settings' );
}
/**
* Create icons folder (quote-llama) in uploads.
*
* @since 1.3.3
* @access private
*/
private function dir_create() {
$upload_dir = wp_upload_dir();
if ( ! empty( $upload_dir['basedir'] ) ) {
$icon_dirname = $upload_dir['basedir'] . '/quotes-llama';
if ( ! file_exists( $icon_dirname ) ) {
wp_mkdir_p( $icon_dirname );
}
}
}
/**
* Manage tab - Removes the quotes_llama table from the database.
*
* @since 1.3.4
* @access private
*/
private function db_remove() {
global $wpdb;
$return = $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'quotes_llama' ); // phpcs:ignore
if ( $return ) {
$this->msg = $this->message( 'Transaction completed: Table removed.', 'yay' );
} else {
$this->msg = $this->message( 'Transaction failed: Failed to remove table. - ' . $return, 'nay' );
}
}
/**
* Plugin database table. If plugin table does not exist, create it.
*
* @since 1.0.0
* @access public
*/
public function db_setup() {
global $wpdb;
// Set collation.
$charset_collate = $wpdb->get_charset_collate();
$sql = $wpdb->prepare(
'CREATE TABLE ' . $wpdb->prefix . 'quotes_llama (
quote_id mediumint( 9 ) NOT NULL AUTO_INCREMENT PRIMARY KEY,
quote TEXT NOT NULL,
title_name VARCHAR( 255 ),
first_name VARCHAR( 255 ),
last_name VARCHAR( 255 ),
source VARCHAR( 255 ),
img_url VARCHAR( 255 ),
author_icon VARCHAR( 255 ),
source_icon VARCHAR( 255 ),
category VARCHAR( 255 )
) %1s;', // phpcs:ignore
$charset_collate
);
// Instance of maybe_create_table.
if ( ! function_exists( 'maybe_create_table' ) ) {
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
}
// Create table if not exist already.
$results = maybe_create_table( $wpdb->prefix . 'quotes_llama', $sql );
// If no icon folder, create it.
$this->dir_create();
}
/**
* Plugin database version.
*
* @since 1.3.4
* @var string
*
* @access public
*/
public function db_version() {
return QL_DB_VERSION;
}
/**
* Gets quote category list. This the list of categories available to choose from.
*
* @since 2.0.5
* @access public
*
* @param array $idcategory - Existing categories.
*
* @return string Checkbox - list of categories.
*/
public function get_categories( $idcategory = null ) {
global $wpdb;
// Get all categories.
$ql_category = $this->select_categories( 'categories' );
// stdObject to array. Remove empty values.
foreach ( $ql_category as $ql_cat ) {
if ( ! empty( $ql_cat->category ) ) {
$ql_categ[] = $ql_cat->category;
}
}
if ( isset( $ql_categ ) ) {
// Array to string. To combine singular and plural category entries into single csv line.
$ql_category = implode( ', ', $ql_categ );
// Back to array with values all separated. Strip duplicates.
$ql_category = array_unique( explode( ', ', $ql_category ) );
// Sort the categories.
sort( $ql_category );
}
// For sorting checked categories to top.
$is_checked = '';
$not_checked = '';
// If there are categories already, create checkbox list and check them.
if ( isset( $idcategory ) ) {
// Add new category textbox.
$cat = '';
$cat .= '
';
$cat .= '
Select from Categories:
';
$cat .= '';
// stdObj to array so we can use values as strings.
$ql_category = json_decode( wp_json_encode( $ql_category ), true );
foreach ( $ql_category as $category ) {
// Check category is a string. No categories is an array.
if ( is_string( $category ) ) {
// Category checkboxes. If already a category for this quote, check it.
if ( in_array( $category, $idcategory, true ) ) {
$is_checked .= '
';
} else {
$not_checked .= '
';
}
}
}
} else {
$ql_category = json_decode( wp_json_encode( $ql_category ), true );
// Or just a text list of categories.
$cat = '';
$cat .= '';
$cat .= '';
$cat .= '
';
$cat .= 'Select a category to work with:
';
$cat .= '';
foreach ( $ql_category as $category ) {
if ( is_string( $category ) ) {
$not_checked .= '';
}
}
}
$cat .= $is_checked . $not_checked;
$cat .= '';
return $cat;
}
/**
* Information about plugin.
*
* @since 1.0.0
* @access public
*
* @param string $i - Field name to get.
*
* returns string - Field text.
*/
public function information( $i ) {
$data = get_plugin_data( __FILE__ );
$info = $data[ $i ];
return $info;
}
/**
* Plugin init.
*
* @since 3.0.0
* @access public
*/
public function init() {
// Process early $_POST $_GET.
if ( ! did_action( 'init', array( $this, 'post_get' ) ) ) {
add_action( 'init', array( $this, 'post_get' ) );
}
// Set shortcode for starting plugin.
if ( ! did_action( 'init', array( $this, 'shortcode_add' ) ) ) {
add_action( 'init', array( $this, 'shortcode_add' ) );
}
// Authenticated Ajax access and Non-authenticated Ajax access to the functions.
add_action( 'wp_ajax_select_author', array( $this, 'select_author' ) );
add_action( 'wp_ajax_nopriv_select_author', array( $this, 'select_author' ) );
add_action( 'wp_ajax_select_random', array( $this, 'select_random' ) );
add_action( 'wp_ajax_nopriv_select_random', array( $this, 'select_random' ) );
add_action( 'wp_ajax_select_search', array( $this, 'select_search' ) );
add_action( 'wp_ajax_nopriv_select_search', array( $this, 'select_search' ) );
add_action( 'wp_ajax_select_search_page', array( $this, 'select_search_page' ) );
add_action( 'wp_ajax_nopriv_select_search_page', array( $this, 'select_search_page' ) );
add_action( 'wp_ajax_widget_instance', array( $this, 'widget_instance' ) );
add_action( 'wp_ajax_nopriv_widget_instance', array( $this, 'widget_instance' ) );
// Define i18n language folder in function plugin_text_domain().
add_action( 'text_domain', array( $this, 'text_domain' ) );
// Not logged in, front-end.
if ( ! is_admin() ) {
// Create JS vars.
if ( ! did_action( 'wp_enqueue_scripts', array( $this, 'scripts_localize' ) ) ) {
add_action( 'wp_enqueue_scripts', array( $this, 'scripts_localize' ) );
}
// Register scripts an styles.
if ( ! did_action( 'init', array( $this, 'scripts_register' ) ) ) {
add_action( 'init', array( $this, 'scripts_register' ), 1 );
}
// Widget.
if ( ! did_action( 'widgets_init', array( $this, 'widget_register' ) ) ) {
add_action( 'widgets_init', array( $this, 'widget_register' ) );
}
} else {
// Logged in, back-end.
add_action( 'admin_enqueue_scripts', array( $this, 'scripts_admin' ) );
// Create admin manage links, css, and page fields.
if ( ! has_filter( 'plugin_action_links_' . QL_NAME ) ) {
add_filter( 'plugin_action_links_' . QL_NAME, array( $this, 'manage_link' ) );
}
// Set screen options.
add_filter( 'set-screen-option', array( $this, 'set_option' ), 10, 3 );
// Path to plugin settings.
if ( ! did_action( 'admin_menu', array( $this, 'settings_link' ) ) ) {
add_action( 'admin_menu', array( $this, 'settings_link' ) );
}
// Admin page fields.
if ( ! did_action( 'admin_init', array( $this, 'admin_load' ) ) ) {
add_action( 'admin_init', array( $this, 'admin_load' ) );
}
// Widget.
if ( ! did_action( 'widgets_init', array( $this, 'widget_register' ) ) ) {
add_action( 'widgets_init', array( $this, 'widget_register' ) );
}
}
}
/**
* Insert a quote.
*
* @since 1.0.0
* @access private
*
* @param string $quote required - The text to be quoted.
* @param string $title_name - The authors title.
* @param string $first_name - Authors first and middle name.
* @param string $last_name - Authors last name.
* @param string $source - The source text.
* @param string $img_url - The url to an image file.
* @param string $author_icon - The author icon.
* @param string $source_icon - The source icon.
* @param string $category - Category.
*
* @return string - Message of result.
*/
private function insert( $quote, $title_name = '', $first_name = '', $last_name = '', $source = '', $img_url = '', $author_icon = '', $source_icon = '', $category = '' ) {
global $allowedposttags;
global $wpdb;
if ( ! $quote ) {
return $this->message( __( 'Transaction failed: There was no quote to add to the database.', 'quotes-llama' ), 'nay' );
}
$varget = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->prefix . 'quotes_llama' ) ); // phpcs:ignore
if ( $varget !== $wpdb->prefix . 'quotes_llama' ) {
return $this->message( esc_html__( 'Transaction failed: Database table not found!', 'quotes-llama' ), 'nay' );
} else {
$results = $wpdb->insert( // phpcs:ignore
$wpdb->prefix . 'quotes_llama',
array(
'quote' => $quote,
'title_name' => $title_name,
'first_name' => $first_name,
'last_name' => $last_name,
'source' => $source,
'img_url' => $img_url,
'author_icon' => $author_icon,
'source_icon' => $source_icon,
'category' => $category,
),
array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )
);
if ( false === $results ) {
return $this->message( esc_html__( 'Transaction failed: An error occurred in the MySQL query.', 'quotes-llama' ) . ' - ' . $results, 'nay' );
} else {
return $this->message( esc_html__( 'Transaction completed: Quote Added', 'quotes-llama' ), 'yay' );
}
}
}
/**
* Callback to convert URI match to HTML A element.
* Edit of _make_url_clickable_cb funcion from /includes/formatting.php.
*
* This function was backported from 2.5.0 to 2.3.2. Regex callback for make_clickable().
*
* @since 1.1.1
* @access private
*
* @param array $matches Single Regex Match.
* @return string HTML A element with URI address.
*/
private function make_url_clickable_callback( $matches ) {
$url = $matches[2];
if ( ')' === $matches[3] && strpos( $url, '(' ) ) {
// If the trailing character is a closing parethesis, and the URL has an opening parenthesis in it.
$url .= $matches[3];
// Add the closing parenthesis to the URL. Then we can let the parenthesis balancer do its thing below.
$suffix = '';
} else {
$suffix = $matches[3];
}
// Include parentheses in the URL only if paired.
while ( substr_count( $url, '(' ) < substr_count( $url, ')' ) ) {
$suffix = strrchr( $url, ')' ) . $suffix;
$url = substr( $url, 0, strrpos( $url, ')' ) );
}
$url = esc_url( $url );
if ( empty( $url ) ) {
return $matches[0];
}
if ( 'comment_text' === current_filter() ) {
$rel = 'nofollow ugc';
} else {
$rel = 'nofollow';
}
/**
* Filters the rel value that is added to URL matches converted to links.
*
* @param string $rel The rel value.
* @param string $url The matched URL being converted to a link tag.
*/
$rel = apply_filters( 'make_clickable_rel', $rel, $url );
$rel = esc_attr( $rel );
// Display http in links if enabled.
if ( $this->check_option( 'http_display' ) ) {
$nourl = $url;
} else {
$nourl = preg_replace( '(^https?://)', '', $url );
}
return $matches[1] . "$nourl" . $suffix;
}
/**
* Admin manage plugin link, admin panel -> plugins.
*
* @since 1.0.0
* @access public
*
* @param array $links - Array of existing panel links.
*
* returns array with new link added.
*/
public function manage_link( $links ) {
$plugin_manage_link = 'Manage';
array_unshift( $links, $plugin_manage_link );
return $links;
}
/**
* Success and Error messaging.
*
* @since 1.0.0
* @access public
*
* @param string $msg - The message to echo.
* @param string $yaynay - yay, nay, nonce.
*
* @return string - Html div with message.
*/
public function message( $msg, $yaynay ) {
if ( 'yay' === $yaynay ) {
return '' . esc_html( $msg ) . '
';
}
if ( 'nay' === $yaynay ) {
return '' . esc_html( $msg ) . '
';
}
if ( 'nonce' === $yaynay ) {
return '' . esc_html__( 'Security token mismatch, please reload the page and try again.', 'quotes-llama' ) . '
';
}
}
/**
* Plugin version.
*
* @since 1.3.4
* @var string
*
* @access public
*/
public function plugin_version() {
return QL_PLUGIN_VERSION;
}
/**
* Direct $_POST and $_GET requests.
*
* @since 3.0.0
* @var string
*
* @access public
*/
public function post_get() {
// $_GET for searching admin list table.
if ( isset( $_GET['s'] ) ) {
$llama_admin_search = isset( $_GET['as'] ) ? sanitize_text_field( wp_unslash( $_GET['as'] ) ) : '';
if ( wp_verify_nonce( $llama_admin_search, 'llama_admin_search_nonce' ) ) {
include QL_PATH . 'includes/php/search.php';
}
}
// $_POST Category bulk actions to Delete/Rename a category.
if ( isset( $_POST['ql-delete-cat-btn'] ) || isset( $_POST['ql-rename-cat-btn'] ) ) {
$this->category_delete_rename();
}
// $_GET message to confirm bulk delete.
if ( isset( $_GET['bd'] ) ) {
include QL_PATH . 'includes/php/quote-bulk-delete-confirm.php';
}
// $_GET message to confirm single delete.
if ( isset( $_GET['d'] ) ) {
include QL_PATH . 'includes/php/quote-delete-confirm.php';
}
// $_POST to Export quotes to csv.
if ( isset( $_POST['quotes_llama_export_csv'] ) ) {
include QL_PATH . 'includes/php/export-csv.php';
}
// $_POST to Export quotes to json.
if ( isset( $_POST['quotes_llama_export_json'] ) ) {
include QL_PATH . 'includes/php/export-json.php';
}
// $_POST to Import quotes.
if ( isset( $_POST['quote_llama_import'] ) ) {
include QL_PATH . 'includes/php/import.php';
}
// $_POST to remove quotes_llama table from database.
if ( isset( $_POST['quotes_llama_remove_table'] ) ) {
include QL_PATH . 'includes/php/remove-table.php';
}
// $_POST to add quote.
if ( isset( $_POST['quotes_llama_add_quote'] ) ) {
include QL_PATH . 'includes/php/quote-insert.php';
}
// $_POST to update quote.
if ( isset( $_POST['quotes_llama_save_quote'] ) ) {
include QL_PATH . 'includes/php/quote-update.php';
}
// $_GET to delete a single quote.
if ( isset( $_GET['action'] ) && 'quotes_llama_delete_single' === $_GET['action'] ) {
include QL_PATH . 'includes/php/quote-delete.php';
}
// $_GET to bulk delete. Upper bulk select box is action. Lower bulk select box is action2.
if ( ( isset( $_GET['action'] ) && 'delete' === $_GET['action'] ) || ( isset( $_GET['action2'] ) && 'delete' === $_GET['action2'] ) ) {
include QL_PATH . 'includes/php/quote-bulk-delete.php';
}
}
/**
* Sets url params.
*
* @since 1.0.0
* @access public
*
* @param string $nonce - Nonce.
*
* @return string - return paramaters for url.
*/
public function return_page( $nonce ) {
$return_page = '';
if ( wp_verify_nonce( $nonce, 'delete_edit' ) ) {
// Set the paged param.
if ( isset( $_GET['paged'] ) ) {
$return_page .= '&paged=' . sanitize_text_field( wp_unslash( $_GET['paged'] ) );
}
// Set the search term param.
if ( isset( $_GET['s'] ) ) {
$return_page .= '&s=' . sanitize_text_field( wp_unslash( $_GET['s'] ) );
}
// Set the search column param.
if ( isset( $_GET['sc'] ) ) {
$return_page .= '&sc=' . sanitize_text_field( wp_unslash( $_GET['sc'] ) );
}
// Set the order param.
if ( isset( $_GET['order'] ) ) {
$return_page .= '&order=' . sanitize_text_field( wp_unslash( $_GET['order'] ) );
}
// Set the sort column param.
if ( isset( $_GET['orderby'] ) ) {
$return_page .= '&orderby=' . sanitize_text_field( wp_unslash( $_GET['orderby'] ) );
}
return $return_page;
}
}
/**
* Front-end scripts and styles.
* Localized variables (quotesllamaAjax).
*
* @since 1.0.0
* @access public
*/
public function scripts_register() {
// Javascript functions.
wp_register_script( 'quotesllamaAjax', QL_URL . 'includes/js/quotes-llama.js', array( 'jquery' ), '1.3.6', true );
// Widget css.
wp_register_style( 'quotes-llama-css-widget', QL_URL . 'includes/css/quotes-llama-widget.css', array(), $this->plugin_version() );
// Gallery css.
wp_register_style( 'quotes-llama-css-gallery', QL_URL . 'includes/css/quotes-llama-gallery.css', array(), $this->plugin_version() );
// Page css.
wp_register_style( 'quotes-llama-css-page', QL_URL . 'includes/css/quotes-llama-page.css', array(), $this->plugin_version() );
// Search css.
wp_register_style( 'quotes-llama-css-search', QL_URL . 'includes/css/quotes-llama-search.css', array(), $this->plugin_version() );
// Search results alternate target class css.
wp_register_style( 'quotes-llama-css-search-target', QL_URL . 'includes/css/quotes-llama-search-target.css', array(), $this->plugin_version() );
// Auto css.
wp_register_style( 'quotes-llama-css-auto', QL_URL . 'includes/css/quotes-llama-auto.css', array(), $this->plugin_version() );
// Count css.
wp_register_style( 'quotes-llama-css-count', QL_URL . 'includes/css/quotes-llama-count.css', array(), $this->plugin_version() );
// ID css.
wp_register_style( 'quotes-llama-css-id', QL_URL . 'includes/css/quotes-llama-id.css', array(), $this->plugin_version() );
// All css.
wp_register_style( 'quotes-llama-css-all', QL_URL . 'includes/css/quotes-llama-all.css', array(), $this->plugin_version() );
// Center image above quote css.
wp_register_style( 'quotes-llama-css-image-center', QL_URL . 'includes/css/quotes-llama-image-center.css', array(), $this->plugin_version() );
// Make image round css.
wp_register_style( 'quotes-llama-css-image-round', QL_URL . 'includes/css/quotes-llama-image-round.css', array(), $this->plugin_version() );
// Align quote to center css.
wp_register_style( 'quotes-llama-css-quote-center', QL_URL . 'includes/css/quotes-llama-quote-center.css', array(), $this->plugin_version() );
// Align quote to left css.
wp_register_style( 'quotes-llama-css-quote-left', QL_URL . 'includes/css/quotes-llama-quote-left.css', array(), $this->plugin_version() );
// Align quote to right css.
wp_register_style( 'quotes-llama-css-quote-right', QL_URL . 'includes/css/quotes-llama-quote-right.css', array(), $this->plugin_version() );
// Format icon images css.
wp_register_style( 'quotes-llama-css-icons-format', QL_URL . 'includes/css/quotes-llama-icons-format.css', array(), $this->plugin_version() );
}
/**
* Front-end styles, settings and ocalizations that are loaded in all short-codes and widgets.
*
* @since 1.0.0
* @access public
*/
public function scripts_localize() {
// Javascript variable arrays quotesllamaOption and quotesllamaAjax, Front-end.
wp_localize_script(
'quotesllamaAjax',
'quotesllamaOption',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'BackgroundColor' => isset( $this->plugin_options['background_color'] ) ? $this->plugin_options['background_color'] : '#444',
'ForegroundColor' => isset( $this->plugin_options['foreground_color'] ) ? $this->plugin_options['foreground_color'] : 'silver',
'GalleryInterval' => isset( $this->plugin_options['gallery_timer_interval'] ) ? $this->plugin_options['gallery_timer_interval'] : 12,
'TransitionSpeed' => isset( $this->plugin_options['transition_speed'] ) ? $this->plugin_options['transition_speed'] : 1000,
'GalleryMinimum' => isset( $this->plugin_options['gallery_timer_minimum'] ) ? $this->plugin_options['gallery_timer_minimum'] : 10,
'GalleryShowTimer' => isset( $this->plugin_options['gallery_timer_show'] ) ? $this->plugin_options['gallery_timer_show'] : false,
'Sidebarpos' => isset( $this->plugin_options['sidebar'] ) ? $this->plugin_options['sidebar'] : 'left',
'Limit' => isset( $this->plugin_options['character_limit'] ) ? $this->plugin_options['character_limit'] : 0,
'Ellipses' => isset( $this->plugin_options['ellipses_text'] ) ? $this->plugin_options['ellipses_text'] : '...',
'SourceNewLine' => isset( $this->plugin_options['source_newline'] ) ? $this->plugin_options['source_newline'] : 'br',
'MoreText' => isset( $this->plugin_options['read_more_text'] ) ? $this->plugin_options['read_more_text'] : '»',
'ShowIcons' => isset( $this->plugin_options['show_icons'] ) ? $this->plugin_options['show_icons'] : false,
'AuthorIcon' => isset( $this->plugin_options['author_icon'] ) ? $this->plugin_options['author_icon'] : 'edit',
'SourceIcon' => isset( $this->plugin_options['source_icon'] ) ? $this->plugin_options['source_icon'] : 'migrate',
'LessText' => isset( $this->plugin_options['read_less_text'] ) ? $this->plugin_options['read_less_text'] : '«',
'BorderRadius' => isset( $this->plugin_options['border_radius'] ) ? $this->plugin_options['border_radius'] : false,
'ImageAtTop' => isset( $this->plugin_options['image_at_top'] ) ? $this->plugin_options['image_at_top'] : false,
'AlignQuote' => isset( $this->plugin_options['align_quote'] ) ? $this->plugin_options['align_quote'] : 'left',
'ImageAtTop' => isset( $this->plugin_options['image_at_top'] ) ? $this->plugin_options['image_at_top'] : false,
'ThisDIR' => $this->icons_dir,
'ThisURL' => $this->icons_url,
'AllQuotes' => $this->select_all(),
)
);
// Main css Front-end.
wp_enqueue_style( 'quotes-llama-css-style', QL_URL . 'includes/css/quotes-llama.css', array(), $this->plugin_version() );
// Enable admin dashicons set for Front-end.
wp_enqueue_style( 'dashicons-style', get_stylesheet_uri(), array( 'dashicons' ), $this->plugin_version() );
}
/**
* Dashboard scripts, localizations and styles.
*
* @since 1.0.0
* @access public
*/
public function scripts_admin() {
// Javascript functions.
wp_enqueue_script( 'quotesllamaAjax', QL_URL . 'includes/js/quotes-llama.js', array( 'jquery' ), '1.3.6', true );
// Javascript variable arrays quotesllamaOption and quotesllamaAjax, Back-end.
wp_localize_script(
'quotesllamaAjax',
'quotesllamaOption',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ThisURL' => $this->icons_url,
)
);
// Javascript functions for dash-icons selection drop-list.
wp_enqueue_script( 'quotesllamaDashIcons', QL_URL . 'includes/js/dash-icons.js', array( 'jquery' ), $this->plugin_version(), true );
// Necessary to use all media JS APIs.
wp_enqueue_media();
// Admin css.
wp_enqueue_style( 'quotes-llama-css-admin', QL_URL . 'includes/css/quotes-llama-admin.css', array(), $this->plugin_version() );
// Dash-icons css.
wp_enqueue_style( 'quotesllamaDashIcons', QL_URL . 'includes/css/dash-icons.css', array(), $this->plugin_version() );
}
/**
* All quotes.
*
* @since 3.1.0
* @access public
*/
public function select_all() {
global $wpdb;
$quotes = $wpdb->get_results( // phpcs:ignore
'SELECT * FROM ' .
$wpdb->prefix .
'quotes_llama',
ARRAY_A
);
return $quotes;
}
/**
* All quotes for a author.
*
* @since 1.0.0
* @access public
*
* @param string $cat - Category.
* @param int $qlcount - How many quotes.
*/
public function select_author( $cat = '', $qlcount = 1 ) {
global $wpdb;
// Page, get all quotes for a author.
if ( isset( $_POST['author'] ) ) {
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
$san_title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '';
$san_first = isset( $_POST['first'] ) ? sanitize_text_field( wp_unslash( $_POST['first'] ) ) : '';
$san_last = isset( $_POST['last'] ) ? sanitize_text_field( wp_unslash( $_POST['last'] ) ) : '';
$quotes = null;
if ( wp_verify_nonce( $nonce, 'quotes_llama_nonce' ) ) {
if ( '' !== $san_title ) {
$title = $san_title;
} else {
$title = false;
}
if ( '' !== $san_first ) {
$first = $san_first;
} else {
$first = false;
}
if ( '' !== $san_last ) {
$last = $san_last;
} else {
$last = false;
}
// If title, first and last name.
if ( $first && $last && $title ) {
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE title_name = %s AND first_name = %s AND last_name = %s ORDER BY last_name, first_name, quote',
$title,
$first,
$last
)
);
// If title and first name only.
} elseif ( $first && empty( $last ) && $title ) {
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE title_name = %s AND first_name = %s ORDER BY first_name, quote',
$title,
$first
)
);
// If title and last name only.
} elseif ( empty( $first ) && $last && $title ) {
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE title_name = %s AND last_name = %s ORDER BY last_name, quote',
$title,
$last
)
);
// If first and last with no title.
} elseif ( $first && $last ) {
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE (title_name IS NULL OR title_name = " ") AND first_name = %s AND last_name = %s ORDER BY last_name, first_name, quote',
$first,
$last
)
);
// If first with no last or title.
} elseif ( $first && empty( $last ) ) {
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE (title_name IS NULL OR title_name = " ") AND first_name = %s ORDER BY first_name, quote',
$first
)
);
// If last with no first or title.
} elseif ( empty( $first ) && $last ) {
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE (title_name IS NULL OR title_name = " ") AND last_name = %s ORDER BY last_name, quote',
$last
)
);
}
// Array of allowed html.
$allowed_html = $this->allowed_html( 'quote' );
// Include Page class.
if ( ! class_exists( 'QuotesLlama_Page' ) ) {
require_once 'includes/classes/class-quotesllama-page.php';
}
$page = new QuotesLlama_Page();
if ( $quotes ) {
echo wp_kses( $page->ql_page_author( $quotes ), $allowed_html );
}
die();
} else {
$this->msg = $this->message( '', 'nonce' );
}
}
}
/**
* Get authors list for page.
*
* @since 1.0.0
* @access public
*
* @param int $quote_id - Id of quote.
* @param string $cat - Category.
*
* @return result array.
*/
public function select_authors( $quote_id = 0, $cat = '' ) {
global $wpdb;
// Page, Get authors first, last name for sidebar author list.
if ( 'author_list' === $quote_id ) {
if ( $cat ) {
// Category string to array.
$cats = explode( ', ', $cat );
// Begin building query string.
$cat_query = 'SELECT
title_name,
first_name,
last_name,
count(first_name) AS quotecount FROM ' . $wpdb->prefix . 'quotes_llama WHERE (';
// Setup each category placeholder and its value.
foreach ( $cats as $categ ) {
$cat_query .= 'category LIKE %s OR ';
$cat_values[] = '%' . $categ . '%';
}
// Strip trailing OR from query string.
$cat_query = substr( $cat_query, 0, -4 );
// Finish building query string.
$cat_query .= ') GROUP BY title_name, last_name, first_name ORDER BY last_name';
$authors = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
$cat_query, // phpcs:ignore
$cat_values
)
);
return $authors;
}
$authors = $wpdb->get_results( // phpcs:ignore
'SELECT
title_name,
first_name,
last_name,
count(first_name) AS quotecount FROM ' . $wpdb->prefix . 'quotes_llama' .
' GROUP BY title_name, last_name,
first_name ORDER BY last_name'
);
return $authors;
}
}
/**
* Get categories list.
*
* @since 1.0.0
* @access private
*
* @param mixed $quote_id - Should be categories.
*
* @return result array.
*/
private function select_categories( $quote_id = 0 ) {
global $wpdb;
// All categories list.
if ( 'categories' === $quote_id ) {
$categories = $wpdb->get_results( // phpcs:ignore
'SELECT category FROM ' . $wpdb->prefix . 'quotes_llama' .
' GROUP BY category'
);
return $categories;
}
}
/**
* Get quotes by ID.
*
* @since 1.0.0
* @access public
*
* @param int $quote_id - Id of quote.
*
* @return result array.
*/
public function select_id( $quote_id = 0 ) {
global $wpdb;
// Get quote by id.
if ( is_numeric( $quote_id ) && $quote_id > 0 ) {
$quote_data = $wpdb->get_row( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote_id,
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE quote_id = %d',
$quote_id
),
ARRAY_A
);
// Set default icons if none. This is for backwards compatibility.
if ( empty( $quote_data['author_icon'] ) ) {
$quote_data['author_icon'] = $this->check_option( 'author_icon' );
}
if ( empty( $quote_data['source_icon'] ) ) {
$quote_data['source_icon'] = $this->check_option( 'source_icon' );
}
return $quote_data;
}
}
/**
* Get random quotes.
*
* @since 1.0.0
* @access public
*
* @param mixed $quote_id - Id of quote.
* @param string $cat - Category.
* @param int $qlcount - How many quotes.
* @param int $nonce - nonce.
*
* @return result array.
*/
public function select_random( $quote_id = 0, $cat = '', $qlcount = 1, $nonce = '' ) {
global $wpdb;
$post_nonce = isset( $_POST['quotes_llama_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['quotes_llama_nonce'] ) ) : '';
if ( $post_nonce ) {
$nonce = $post_nonce;
}
if ( wp_verify_nonce( $nonce, 'quotes_llama_nonce' ) ) {
// Get random quote from all or category for .ajax request.
if ( 'quotes_llama_random' === $quote_id || isset( $_POST['quotes_llama_random'] ) ) {
$category = isset( $_REQUEST['quotes_llama_category'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['quotes_llama_category'] ) ) : null;
// Use $_POST before $cat.
$thiscat = isset( $category ) ? $category : $cat;
// If getting several quotes.
if ( $thiscat && $qlcount > 1 ) {
// Category string to array.
$cats = explode( ', ', $thiscat );
// Begin building query string.
$cat_query = 'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama WHERE (';
// Setup each category placeholder and its value.
foreach ( $cats as $categ ) {
$cat_query .= 'category LIKE %s OR ';
$cat_values[] = '%' . $categ . '%';
}
// Strip trailing OR from query string.
$cat_query = substr( $cat_query, 0, -4 );
// How many quotes to get? %d.
$cat_values[] = $qlcount;
// Finish building query string.
$cat_query .= ') ORDER BY RAND() LIMIT %d';
$rand_data = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
$cat_query, // phpcs:ignore
$cat_values
),
ARRAY_A
);
} elseif ( $qlcount > 1 ) {
$rand_data = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' ORDER BY RAND() LIMIT %d',
$qlcount
),
ARRAY_A
);
}
// If just a single quote.
if ( $thiscat && 1 === $qlcount ) {
// Category string to array.
$cats = explode( ', ', $thiscat );
// Begin building query string.
$cat_query = 'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama WHERE (';
// Setup each category placeholder and its value.
foreach ( $cats as $categ ) {
$cat_query .= 'category LIKE %s OR ';
$cat_values[] = '%' . $categ . '%';
}
// Strip trailing OR from query string.
$cat_query = substr( $cat_query, 0, -4 );
// Finish building query string.
$cat_query .= ') ORDER BY RAND() LIMIT 1';
$rand_data = $wpdb->get_row( // phpcs:ignore
$wpdb->prepare(
$cat_query, // phpcs:ignore
$cat_values
),
ARRAY_A
);
} elseif ( 1 === $qlcount ) {
$rand_data = $wpdb->get_row( // phpcs:ignore
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' ORDER BY RAND() LIMIT 1',
ARRAY_A
);
}
// Set default icons if none. This is for backwards compatibility.
if ( empty( $rand_data['author_icon'] ) ) {
$rand_data['author_icon'] = $this->check_option( 'author_icon' );
}
if ( empty( $rand_data['source_icon'] ) ) {
$rand_data['source_icon'] = $this->check_option( 'source_icon' );
}
// Make quote and source clickable before sending to ajax.
if ( $rand_data ) {
$rand_data['quote'] = isset( $rand_data['quote'] ) ? trim( $this->clickable( $rand_data['quote'] ) ) : '';
$rand_data['source'] = isset( $rand_data['source'] ) ? trim( $this->clickable( $rand_data['source'] ) ) : '';
}
// If a quote for gallery.
if ( isset( $_POST['quotes_llama_random'] ) ) {
echo wp_json_encode( $rand_data );
die();
}
// If just a random quote for sidebar.
if ( 'quotes_llama_random' === $quote_id ) {
return $rand_data;
}
}
} else {
$this->msg = $this->message( '', 'nonce' );
}
}
/**
* Search.
*
* @since 1.0.0
* @access public
*
* @param int $quote_id - Id of quote.
* @param string $cat - Category.
* @param int $qlcount - How many quotes.
*/
public function select_search( $quote_id = 0, $cat = '', $qlcount = 1 ) {
global $wpdb;
// Search, search bar and submit button only.
if ( isset( $_POST['search_form'] ) ) {
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
$term = isset( $_POST['term'] ) ? sanitize_text_field( wp_unslash( $_POST['term'] ) ) : '';
$search_column = isset( $_POST['sc'] ) ? sanitize_text_field( wp_unslash( $_POST['sc'] ) ) : 'quote';
$target_class = isset( $_POST['target'] ) ? sanitize_text_field( wp_unslash( $_POST['target'] ) ) : 'quotes-llama-search';
// Include Template Search Results class.
if ( ! class_exists( 'QuotesLlama_Search_Results' ) ) {
require_once 'includes/classes/class-quotesllama-search-results.php';
}
$search_results = new QuotesLlama_Search_Results();
if ( wp_verify_nonce( $nonce, 'quotes_llama_nonce' ) ) {
$like = '%' . $wpdb->esc_like( $term ) . '%';
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE %1s LIKE %s' . // phpcs:ignore
'ORDER BY title_name, last_name, first_name, quote',
$search_column,
$like
)
);
$search_results->ql_search_result( $quotes, $target_class );
die();
} else {
$this->msg = $this->message( '', 'nonce' );
die();
}
}
}
/**
* Page Search.
*
* @since 1.0.0
* @access public
*
* @param int $quote_id - Id of quote.
* @param string $cat - Category.
* @param int $qlcount - How many quotes.
*/
public function select_search_page( $quote_id = 0, $cat = '', $qlcount = 1 ) {
global $wpdb;
// Page, Search for quote.
if ( isset( $_POST['search_for_quote'] ) ) {
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
$term = isset( $_POST['term'] ) ? sanitize_text_field( wp_unslash( $_POST['term'] ) ) : '';
$search_column = isset( $_POST['sc'] ) ? sanitize_text_field( wp_unslash( $_POST['sc'] ) ) : 'quote';
// Include Template Page class.
if ( ! class_exists( 'QuotesLlama_Page' ) ) {
require_once 'includes/classes/class-quotesllama-page.php';
}
$ql_page = new QuotesLlama_Page();
if ( wp_verify_nonce( $nonce, 'quotes_llama_nonce' ) ) {
$like = '%' . $wpdb->esc_like( $term ) . '%';
$quotes = $wpdb->get_results( // phpcs:ignore
$wpdb->prepare(
'SELECT
quote,
title_name,
first_name,
last_name,
source,
img_url,
author_icon,
source_icon,
category FROM ' . $wpdb->prefix . 'quotes_llama' .
' WHERE %1s LIKE %s' . // phpcs:ignore
'ORDER BY title_name, last_name, first_name, quote',
$search_column,
$like
)
);
$ql_page->ql_page_search( $quotes );
die();
} else {
$this->msg = $this->message( '', 'nonce' );
die();
}
}
}
/**
* Author/source separator, either a comma or new line.
*
* @since 1.0.0
* @access public
*
* @param string $s - which separator to use.
*
* @return string - html used to separate.
*/
public function separate( $s ) {
if ( 'br' === $s ) {
$a = '
';
} else {
$a = ', ';
}
return $a;
}
/**
* Load backend.
*
* @since 3.0.0
* @access public
*/
public function settings_link() {
// Include Admin class.
if ( ! class_exists( 'QuotesLlama_Admin' ) ) {
require_once 'includes/classes/class-quotesllama-admin.php';
}
$ql_admin = new QuotesLlama_Admin();
$ql_admin->msg = $this->msg;
$ql_admin->plugin_settings_link();
}
/**
* Sets value for table screen options in admin page.
*
* @since 1.0.0
* @access public
*
* @param string $status - The value to save instead of the option value.
* @param string $name - The option name.
* @param string $value - The option value.
*
* @return string - Sanitized string.
*/
public function set_option( $status, $name, $value ) {
return $value;
}
/**
* Base shortcode.
*
* @since 1.0.0
* @access public
*/
public function shortcode_add() {
// Set quotes-llama to base short-code.
add_shortcode( 'quotes-llama', array( $this, 'shortcodes' ) );
}
/**
* Start plugin via template or page shortcodes. The order of execution is important!
*
* @since 1.0.0
* @access public
*
* @param array $atts - mode,class,id,all,cat,quotes,limit.
*/
public function shortcodes( $atts ) {
$att_array = shortcode_atts(
array(
'mode' => 'quote',
'class' => 'quotes-llama-search',
'id' => 0,
'all' => 0,
'cat' => 0,
'quotes' => 0,
'limit' => 5,
),
$atts
);
// Nonce for [quotes-llama all=..] short-codes.
$nonce = wp_create_nonce( 'quotes_llama_all' );
// [quotes-llama mode='auto' cat='category'] Display quote from category in auto-refresh mode.
if ( $att_array['cat'] && ( 'auto' === $att_array['mode'] ) ) {
if ( ! class_exists( 'QuotesLlama_Auto' ) ) {
require_once 'includes/classes/class-quotesllama-auto.php';
}
$ql_auto = new QuotesLlama_Auto();
return $ql_auto->ql_auto( $att_array['cat'] );
}
// [quotes-llama mode='auto'] Auto-refresh a random quote. This should be called last in auto modes.
if ( 'auto' === $att_array['mode'] ) {
if ( ! class_exists( 'QuotesLlama_Auto' ) ) {
require_once 'includes/classes/class-quotesllama-auto.php';
}
$ql_auto = new QuotesLlama_Auto();
return $ql_auto->ql_auto();
}
// [quotes-llama mode='gallery' cat='category'] Display gallery.
if ( 'gallery' === $att_array['mode'] ) {
if ( ! class_exists( 'QuotesLlama_Gallery' ) ) {
require_once 'includes/classes/class-quotesllama-gallery.php';
}
$ql_gallery = new QuotesLlama_Gallery();
// [quotes-llama mode='gallery' cat='category'] Display quote from category in gallery mode.
if ( $att_array['cat'] && ( 'gallery' === $att_array['mode'] ) ) {
return $ql_gallery->ql_gallery( $att_array['cat'] );
}
// [quotes-llama mode='gallery'] This should be called last in gallery modes.
if ( 'gallery' === $att_array['mode'] ) {
return $ql_gallery->ql_gallery();
}
}
// [quotes-llama mode='search'] Search bar only.
if ( 'search' === $att_array['mode'] ) {
if ( ! class_exists( 'QuotesLlama_Search' ) ) {
require_once 'includes/classes/class-quotesllama-search.php';
}
$ql_search = new QuotesLlama_Search();
return $ql_search->ql_search( wp_create_nonce( 'quotes_llama_nonce' ), $att_array['class'] );
}
// [quotes-llama mode='page' cat='category'] Quotes Page of a category of quotes.
if ( $att_array['cat'] && ( 'page' === $att_array['mode'] ) ) {
if ( ! class_exists( 'QuotesLlama_Page' ) ) {
require_once 'includes/classes/class-quotesllama-page.php';
}
$ql_page = new QuotesLlama_Page();
return $ql_page->ql_page( wp_create_nonce( 'quotes_llama_nonce' ), $att_array['cat'] );
}
// [quotes-llama mode='page'] Quotes Page of all quotes. This should be called last in page modes.
if ( 'page' === $att_array['mode'] ) {
if ( ! class_exists( 'QuotesLlama_Page' ) ) {
require_once 'includes/classes/class-quotesllama-page.php';
}
$ql_page = new QuotesLlama_Page();
return $ql_page->ql_page( wp_create_nonce( 'quotes_llama_nonce' ), '' );
}
// [quotes-llama] A single random quote.
if ( 'quote' === $att_array['mode'] &&
0 === $att_array['id'] &&
0 === $att_array['all'] &&
0 === $att_array['cat'] &&
0 === $att_array['quotes']
) {
if ( ! class_exists( 'QuotesLlama_Quote' ) ) {
require_once 'includes/classes/class-quotesllama-quote.php';
}
$ql_quote = new QuotesLlama_Quote();
return $ql_quote->ql_quote();
}
// [quotes-llama quotes='#' cat='category'] Get a number of static quotes from category.
if ( $att_array['quotes'] && $att_array['cat'] ) {
if ( ! class_exists( 'QuotesLlama_Quotes' ) ) {
require_once 'includes/classes/class-quotesllama-quotes.php';
}
$ql_queries = new QuotesLlama_quotes();
return $ql_queries->ql_quotes( $att_array['cat'], $att_array['quotes'] );
}
// [quotes-llama quotes='#'] Get a number of random static quotes. This should be called last in quote and quotes.
if ( $att_array['quotes'] ) {
if ( ! class_exists( 'QuotesLlama_Quotes' ) ) {
require_once 'includes/classes/class-quotesllama-quotes.php';
}
$ql_queries = new QuotesLlama_Quotes();
return $ql_queries->ql_quotes( '', $att_array['quotes'] );
}
// [quotes-llama id='id, ids'] Quotes by the ids.
if ( $att_array['id'] ) {
if ( ! class_exists( 'QuotesLlama_ID' ) ) {
require_once 'includes/classes/class-quotesllama-id.php';
}
$ql_all = new QuotesLlama_ID();
$quote_id = explode( ',', $atts['id'] );
$id_string = '';
foreach ( $quote_id as $id ) {
$id_string .= $ql_all->ql_id( $id );
}
return $id_string;
}
// [quotes-llama all=''] short-codes.
if ( $att_array['all'] ) {
if ( ! class_exists( 'QuotesLlama_All' ) ) {
require_once 'includes/classes/class-quotesllama-all.php';
}
$ql_all = new QuotesLlama_All();
// [quotes-llama all='random, ascend, descend, id' cat='category'] All quotes by categories. This should be called first in 'all' shortcodes.
if ( $att_array['all'] && $att_array['cat'] ) {
return $ql_all->ql_all( $att_array['all'], $att_array['cat'], $att_array['limit'], $nonce );
}
// [quotes-llama all='random'] All quotes by random.
if ( 'random' === $att_array['all'] ) {
return $ql_all->ql_all( 'random', '', $att_array['limit'], $nonce );
}
// [quotes-llama all='ascend'] All quotes ascending.
if ( 'ascend' === $att_array['all'] ) {
return $ql_all->ql_all( 'ascend', '', $att_array['limit'], $nonce );
}
// [quotes-llama all='descend'] All quotes descending.
if ( 'descend' === $att_array['all'] ) {
return $ql_all->ql_all( 'descend', '', $att_array['limit'], $nonce );
}
// [quotes-llama all='id'] All quotes by id.
if ( 'id' === $att_array['all'] ) {
return $ql_all->ql_all( 'id', '', $att_array['limit'], $nonce );
}
}
// [quotes-llama cat='category'] Display random quote from a category. This should be called last in cat shortcodes.
if ( $att_array['cat'] ) {
if ( ! class_exists( 'QuotesLlama_Quote' ) ) {
require_once 'includes/classes/class-quotesllama-quote.php';
}
$ql_quote = new QuotesLlama_Quote();
return $ql_quote->ql_quote( $att_array['cat'] );
}
}
/**
* Show a icon from image or dashicon.
*
* @since 1.0.0
* @access public
*
* @param string $icon - which dash-icon or image name.
*
* @return string - html span with icon image or dashicon class.
*/
public function show_icon( $icon ) {
$show_icons = $this->check_option( 'show_icons' );
// If options allow icons.
if ( $show_icons ) {
// Image extensions.
$image_extensions = array(
'png',
'jpg',
'jpeg',
'gif',
'bmp',
'svg',
);
// Get extenstion of image file.
$ext = strtolower( pathinfo( $icon, PATHINFO_EXTENSION ) );
// If extenstion in array or is a dashicon.
if ( in_array( $ext, $image_extensions, true ) ) {
return '';
} else {
return '';
}
}
return '';
}
/**
* Define i18n language folder.
*
* @since 1.0.0
* @access private
*/
private function text_domain() {
load_plugin_textdomain( 'quotes-llama', false, QL_URL . 'lang' );
}
/**
* Registers the widget class.
*
* @since 1.0.0
* @access public
*/
public function widget_register() {
if ( ! class_exists( 'QuotesLlama_Widget' ) ) {
require_once 'includes/classes/class-quotesllama-widget.php';
}
register_widget( 'Quotes_Llama\QuotesLlama_Widget' );
}
/**
* Renders a widget instance in the sidebar.
*
* @since 1.0.0
* @access public
*
* @param int $quote_id - list of ids to gets.
* @param bool $show_author - show the author.
* @param bool $show_source - show the source.
* @param bool $show_image - show the image.
* @param bool $next_quote - Display next quote link.
* @param bool $gallery - Auto-refresh.
* @param string $category - Category.
* @param string $div_instance - previous instance id so we can replace it instead of nest into it.
* @param string $nonce - Nonce.
*/
public function widget_instance( $quote_id = 0, $show_author = true, $show_source = true, $show_image = true, $next_quote = true, $gallery = false, $category = '', $div_instance = 0, $nonce = '' ) {
$post_nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
if ( $post_nonce ) {
$nonce = $post_nonce;
}
if ( wp_verify_nonce( $nonce, 'quotes_llama_nonce' ) ) {
$use_comma = false;
$source_newline = $this->check_option( 'source_newline' );
if ( isset( $_POST['author'] ) ) {
$show_author = sanitize_text_field( wp_unslash( $_POST['author'] ) );
}
if ( isset( $_POST['source'] ) ) {
$show_source = sanitize_text_field( wp_unslash( $_POST['source'] ) );
}
if ( isset( $_POST['img'] ) ) {
$show_image = sanitize_text_field( wp_unslash( $_POST['img'] ) );
}
if ( isset( $_POST['next_quote'] ) ) {
$next_quote = sanitize_text_field( wp_unslash( $_POST['next_quote'] ) );
}
if ( isset( $_POST['gallery'] ) ) {
$gallery = sanitize_text_field( wp_unslash( $_POST['gallery'] ) );
}
if ( isset( $_POST['quote_id'] ) ) {
$quote_id = sanitize_text_field( wp_unslash( $_POST['quote_id'] ) );
}
if ( isset( $_POST['category'] ) ) {
$category = sanitize_text_field( wp_unslash( $_POST['category'] ) );
}
if ( isset( $_POST['div_instance'] ) ) {
$div_instance = sanitize_text_field( wp_unslash( $_POST['div_instance'] ) );
}
if ( ! $div_instance ) {
$div_instance = 'q' . wp_rand( 1000, 100000 );
}
// Gallery widget mode.
if ( $gallery ) {
?>
select_random( 'quotes_llama_random', $category, 1, $nonce );
} else {
$quote_data = $this->select_random( 'quotes_llama_random', '', 1, $nonce );
}
// Get a quote by the id.
if ( $quote_id > 0 ) {
// Disable auto-refresh.
$gallery = false;
// Get quote by its ID.
$quote_data = $this->select_id( $quote_id, '' );
}
$image = '';
$author_source = '';
// Source icon.
$source_icon = $this->show_icon( $quote_data['source_icon'] );
// If showing image, build string.
if ( $show_image ) {
$isimage = isset( $quote_data['img_url'] ) ? $quote_data['img_url'] : '';
if ( $isimage && ! empty( $isimage ) ) {
$image_exist = esc_url( $isimage );
$image = '
';
}
}
// Span for author and source.
$author_source = '';
} else {
$author_source .= '';
}
?>