Advertisement
Guest User

slidedeck

a guest
Aug 4th, 2012
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 137.52 KB | None | 0 0
  1. <?php
  2. /**
  3.  * SlideDeck 2 Lite for WordPress - Slider Widget
  4.  *
  5.  * Create SlideDecks on your WordPress blogging platform. Manage SlideDeck
  6.  * content and insert them into templates and posts.
  7.  *
  8.  * @package SlideDeck
  9.  * @subpackage SlideDeck 2 Lite
  10.  * @author dtelepathy
  11.  */
  12. /*
  13.  Plugin Name: SlideDeck 2 Lite
  14.  Plugin URI: http://www.slidedeck.com/wordpress
  15.  Description: Create SlideDecks on your WordPress blogging platform and insert them into templates and posts.
  16.  Version: 2.1.20120724
  17.  Author: digital-telepathy
  18.  Author URI: http://www.dtelepathy.com
  19.  License: GPL3
  20.  */
  21. /*
  22.  Copyright 2012 digital-telepathy  (email : support@digital-telepathy.com)
  23.  
  24.  This file is part of SlideDeck.
  25.  
  26.  SlideDeck is free software: you can redistribute it and/or modify
  27.  it under the terms of the GNU General Public License as published by
  28.  the Free Software Foundation, either version 3 of the License, or
  29.  (at your option) any later version.
  30.  
  31.  SlideDeck is distributed in the hope that it will be useful,
  32.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  33.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  34.  GNU General Public License for more details.
  35.  
  36.  You should have received a copy of the GNU General Public License
  37.  along with SlideDeck.  If not, see <http://www.gnu.org/licenses/>.
  38.  */
  39.  
  40. class SlideDeckLitePlugin {
  41.     var $package_slug = 'single';
  42.     static $namespace = "slidedeck";
  43.     static $friendly_name = "SlideDeck 2";
  44.     static $cohort_name = 'ecf8915';
  45.     static $cohort_variation = '';
  46.  
  47.     // Generally, we are not installing addons. If we are, this gets set to true.
  48.     static $slidedeck_addons_installing = false;
  49.  
  50.     // Static variable of addons that are currently installed
  51.     static $addons_installed = array( 'tier_5' => 'tier_5' );
  52.  
  53.     var $decks = array( );
  54.  
  55.     // Available sources to SlideDeck 2
  56.     var $sources = array( );
  57.  
  58.     // Default plugin options
  59.     var $defaults = array(
  60.         'disable_wpautop' => false,
  61.         'dont_enqueue_scrollwheel_library' => false,
  62.         'dont_enqueue_easing_library' => false,
  63.         'disable_edit_create' => false,
  64.         'twitter_user' => "",
  65.         'iframe_by_default' => false
  66.     );
  67.  
  68.     // JavaScript to be run in the footer of the page
  69.     var $footer_scripts = "";
  70.  
  71.     // Styles to override Lens and Deck styles
  72.     var $footer_styles = "";
  73.  
  74.     // Boolean to determine if video JavaScript files need to be loaded
  75.     var $load_video_scripts = false;
  76.  
  77.     // Loaded sources
  78.     var $loadedSources = array( );
  79.  
  80.     // Loaded slide type scripts
  81.     var $loaded_slide_styles = array( );
  82.  
  83.     // Loaded slide type styles
  84.     var $loaded_slide_scripts = array( );
  85.  
  86.     // WordPress Menu Items
  87.     var $menu = array( );
  88.  
  89.     // Name of the option_value to store plugin options in
  90.     var $option_name = "slidedeck_global_options";
  91.  
  92.     var $sizes = array( 'small' => array( 'label' => "Small", 'width' => 300, 'height' => 300 ), 'medium' => array( 'label' => "Medium", 'width' => 500, 'height' => 500 ), 'large' => array( 'label' => "Large", 'width' => 960, 'height' => 500 ), 'custom' => array( 'label' => "Custom", 'width' => 500, 'height' => 500 ) );
  93.  
  94.     // Available slide animation transitions
  95.     var $slide_transitions = array( 'stack' => "Card Stack", 'fade' => "Cross-fade", 'flipHorizontal' => "Flip Horizontal", 'flip' => "Flip Vertical", 'slide' => "Slide (Default)" );
  96.  
  97.     // Taxonomy categories for SlideDeck types
  98.     var $taxonomies = array( 'images' => array( 'label' => "Images", 'color' => "#9a153c", 'thumbnail' => '/images/taxonomy-images.png', 'icon' => '/images/taxonomy-images-icon.png' ), 'social' => array( 'label' => "Social", 'color' => "#024962", 'thumbnail' => '/images/taxonomy-social.png', 'icon' => '/images/taxonomy-social-icon.png' ), 'posts' => array( 'label' => "Posts", 'color' => "#3c7120", 'thumbnail' => '/images/taxonomy-posts.png', 'icon' => '/images/taxonomy-posts-icon.png' ), 'videos' => array( 'label' => "Videos", 'color' => "#434343", 'thumbnail' => '/images/taxonomy-videos.png', 'icon' => '/images/taxonomy-videos-icon.png' ), 'feeds' => array( 'label' => "Feeds", 'color' => "#b24702", 'thumbnail' => '/images/taxonomy-feeds.png', 'icon' => '/images/taxonomy-feeds-icon.png' ) );
  99.  
  100.     // Array of lenses that need loading on a page
  101.     var $lenses_included = array( );
  102.  
  103.     // Boolean of whether or not the Lenses have been loaded in the view yet
  104.     var $lenses_loaded = false;
  105.  
  106.     // SlideDeck font @imports being loaded on the page
  107.     var $font_imports_included = array( );
  108.  
  109.     // Options model groups for display in the order to be displayed
  110.     var $options_model_groups = array( 'Appearance', 'Content', 'Navigation', 'Playback' );
  111.  
  112.     // Backgrounds for editor area
  113.     var $stage_backgrounds = array( 'wood' => "Wood", 'light' => "Light", 'dark' => "Dark" );
  114.  
  115.     var $order_options = array( 'post_title' => "Alphabetical", 'post_modified' => "Last Modified", 'slidedeck_source' => "SlideDeck Source" );
  116.  
  117.     var $user_is_back = false;
  118.     var $upgraded_to_tier = false;
  119.     var $highest_tier_install_link = false;
  120.     var $next_available_tier = false;
  121.    
  122.  
  123.     /**
  124.      * Instantiation construction
  125.      *
  126.      * @uses add_action()
  127.      * @uses SlideDeckLitePlugin::wp_register_scripts()
  128.      * @uses SlideDeckLitePlugin::wp_register_styles()
  129.      */
  130.     function __construct( ) {
  131.         SlideDeckLitePlugin::load_constants();
  132.        
  133.         $this->friendly_name = SlideDeckLitePlugin::$friendly_name;
  134.         $this->namespace = SlideDeckLitePlugin::$namespace;
  135.  
  136.         /**
  137.          * Make this plugin available for translation.
  138.          * Translations can be added to the /languages/ directory.
  139.          */
  140.         load_plugin_textdomain( $this->namespace, false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
  141.  
  142.         // Load all library files used by this plugin
  143.         $lib_files = glob( SLIDEDECK2_DIRNAME . '/lib/*.php' );
  144.         foreach( $lib_files as $filename ) {
  145.             include_once ($filename);
  146.         }
  147.  
  148.         // WordPress Pointers helper
  149.         $this->Pointers = new SlideDeckPointers( );
  150.  
  151.         // The Lens primary class
  152.         include_once (SLIDEDECK2_DIRNAME . '/classes/slidedeck-lens.php');
  153.         $this->Lens = new SlideDeckLens( );
  154.  
  155.         // The Cover primary class
  156.         if( file_exists( SLIDEDECK2_DIRNAME . '/classes/slidedeck-covers.php' ) ){
  157.             include_once (SLIDEDECK2_DIRNAME . '/classes/slidedeck-covers.php');
  158.             $this->Cover = new SlideDeckCovers( );
  159.         }
  160.  
  161.         // The Lens scaffold
  162.         include_once (SLIDEDECK2_DIRNAME . '/classes/slidedeck-lens-scaffold.php');
  163.  
  164.         // The Deck primary class for Deck types to child from
  165.         include_once (SLIDEDECK2_DIRNAME . '/classes/slidedeck.php');
  166.  
  167.         // Stock Lenses that come with SlideDeck distribution
  168.         $lens_files = glob( SLIDEDECK2_DIRNAME . '/lenses/*/lens.php' );
  169.         if( is_dir( SLIDEDECK2_CUSTOM_LENS_DIR ) ) {
  170.             if( is_readable( SLIDEDECK2_CUSTOM_LENS_DIR ) ) {
  171.                 // Get additional uploaded custom Lenses
  172.                 $custom_lens_files = (array) glob( SLIDEDECK2_CUSTOM_LENS_DIR . '/*/lens.php' );
  173.                 // Merge Lenses available and loop through to load
  174.                 $lens_files = array_merge( $lens_files, $custom_lens_files );
  175.             }
  176.         }
  177.  
  178.         // Load all the custom Lens types
  179.         foreach( (array) $lens_files as $filename ) {
  180.             if( is_readable( $filename ) ) {
  181.                 include_once ($filename);
  182.  
  183.                 $classname = slidedeck2_get_classname_from_filename( dirname( $filename ) );
  184.                 $prefix_classname = "SlideDeckLens_{$classname}";
  185.                 if( class_exists( $prefix_classname ) ) {
  186.                     $this->lenses[$classname] = new $prefix_classname;
  187.                 }
  188.             }
  189.         }
  190.  
  191.         $source_files = (array) glob( SLIDEDECK2_DIRNAME . '/sources/*/source.php' );
  192.         foreach( (array) $source_files as $filename ) {
  193.             if( is_readable( $filename ) ) {
  194.                 include_once ($filename);
  195.  
  196.                 $slug = basename( dirname( $filename ) );
  197.                 $classname = slidedeck2_get_classname_from_filename( dirname( $filename ) );
  198.                 $prefix_classname = "SlideDeckSource_{$classname}";
  199.                 if( class_exists( $prefix_classname ) ) {
  200.                     $this->sources[$slug] = new $prefix_classname;
  201.                 }
  202.             }
  203.         }
  204.  
  205.         $this->SlideDeck = new SlideDeck( );
  206.  
  207.         $this->add_hooks( );
  208.     }
  209.  
  210.     /**
  211.      * Render a SlideDeck in an iframe
  212.      *
  213.      * Generates an iframe tag with a SlideDeck rendered in it. Only accessible
  214.      * via
  215.      * the shortcode with the iframe property set.
  216.      *
  217.      * @param integer $id SlideDeck ID
  218.      * @param integer $width Width of SlideDeck
  219.      * @param integer $height Height of SlideDeck
  220.      * @param boolean $nocovers Whether or not to include covers in the render
  221.      *
  222.      * @global $wp_scripts
  223.      *
  224.      * @uses SlideDeck::get()
  225.      * @uses SlideDeck::get_unique_id()
  226.      * @uses SlideDeckLitePlugin::get_dimensions()
  227.      * @uses SlideDeckLitePlugin::get_iframe_url()
  228.      *
  229.      * @return string
  230.      */
  231.     private function _render_iframe( $id, $width = null, $height = null, $nocovers = false ) {
  232.         global $wp_scripts;
  233.  
  234.         // Load the SlideDeck itself
  235.         $slidedeck = $this->SlideDeck->get( $id );
  236.  
  237.         // Get the inner and outer dimensions for the SlideDeck
  238.         $dimensions = $this->get_dimensions( $slidedeck );
  239.  
  240.         // Get the IFRAME source URL
  241.         $iframe_url = $this->get_iframe_url( $id );
  242.  
  243.         if( $nocovers )
  244.             $iframe_url .= "&nocovers=1";
  245.  
  246.         // Generate a unique HTML ID
  247.         $slidedeck_unique_id = $this->SlideDeck->get_unique_id( $id );
  248.  
  249.         $html = '<iframe class="slidedeck-iframe-embed" id="' . $slidedeck_unique_id . '" frameborder="0" allowtransparency="yes"  src="' . $iframe_url . '" style="width:' . $dimensions['outer_width'] . 'px;height:' . $dimensions['outer_height'] . 'px;"></iframe>';
  250.  
  251.         return $html;
  252.     }
  253.  
  254.     /**
  255.      * Save a SlideDeck autodraft
  256.      *
  257.      * Saves a SlideDeck auto-draft and returns an array with dimension
  258.      * information, the ID
  259.      * of the auto-draft and the URL for the iframe preview.
  260.      *
  261.      * @param integer $slidedeck_id The ID of the parent SlideDeck
  262.      * @param array $data All data about the SlideDeck being auto-drafted
  263.      *
  264.      * @return array
  265.      */
  266.     private function _save_autodraft( $slidedeck_id, $data ) {
  267.         // Preview SlideDeck object
  268.         $preview = $this->SlideDeck->save_preview( $slidedeck_id, $data );
  269.  
  270.         $dimensions = $this->get_dimensions( $preview );
  271.  
  272.         $iframe_url = $this->get_iframe_url( $preview['id'], $dimensions['width'], $dimensions['height'], $dimensions['outer_width'], $dimensions['outer_height'], true );
  273.  
  274.         $response = $dimensions;
  275.         $response['preview_id'] = $preview['id'];
  276.         $response['preview'] = $preview;
  277.         $response['url'] = $iframe_url;
  278.  
  279.         return $response;
  280.     }
  281.  
  282.     /**
  283.      * uasort() sorting method for sorting by weight property
  284.      *
  285.      * @return boolean
  286.      */
  287.     private function _sort_by_weight( $a, $b ) {
  288.         $default_weight = 100;
  289.  
  290.         $a_weight = is_object( $a ) ? (isset( $a->weight ) ? $a->weight : $default_weight) : (is_array( $a ) && isset( $a['weight'] ) ? $a['weight'] : $default_weight);
  291.         $b_weight = is_object( $b ) ? (isset( $b->weight ) ? $b->weight : $default_weight) : (is_array( $b ) && isset( $b['weight'] ) ? $b['weight'] : $default_weight);
  292.  
  293.         return $a_weight > $b_weight;
  294.     }
  295.  
  296.     /**
  297.      * Get the URL for the specified plugin action
  298.      *
  299.      * @param object $str [optional] Expects the handle passed in the menu
  300.      * definition
  301.      *
  302.      * @uses admin_url()
  303.      *
  304.      * @return The absolute URL to the plugin action specified
  305.      */
  306.     function action( $str = "" ) {
  307.         $path = admin_url( "admin.php?page=" . SLIDEDECK2_BASENAME );
  308.  
  309.         if( !empty( $str ) ) {
  310.             return $path . $str;
  311.         } else {
  312.             return $path;
  313.         }
  314.     }
  315.  
  316.     /**
  317.      * Hook into register_activation_hook action
  318.      *
  319.      * Put code here that needs to happen when your plugin is first activated
  320.      * (database
  321.      * creation, permalink additions, etc.)
  322.      *
  323.      * @uses wp_remote_fopen()
  324.      */
  325.     static function activate( ) {
  326.         SlideDeckLitePlugin::load_constants();
  327.         include_once( dirname( __FILE__ ) . '/lib/template-functions.php' );
  328.        
  329.         if( !is_dir( SLIDEDECK2_CUSTOM_LENS_DIR ) ) {
  330.             if( is_writable( dirname( SLIDEDECK2_CUSTOM_LENS_DIR ) ) ) {
  331.                 mkdir( SLIDEDECK2_CUSTOM_LENS_DIR, 0777 );
  332.             }
  333.         }
  334.  
  335.         self::check_plugin_updates( );
  336.        
  337.  
  338.         $installed_version = get_option( "slidedeck_version", false );
  339.         $installed_license = get_option( "slidedeck_license", false );
  340.  
  341.         if( $installed_license ) {
  342.             if( strtolower( $installed_license ) == "lite" && strtolower( SLIDEDECK2_LICENSE ) == "pro" ) {
  343.                 // Upgrade from Lite to PRO
  344.                 slidedeck2_km( "Upgrade to PRO" );
  345.             }
  346.         }
  347.  
  348.         // First time installation
  349.         if( !$installed_version ) {
  350.             slidedeck2_km( "SlideDeck Installed" );
  351.            
  352.             // Setup the cohorts data
  353.             self::set_cohort_data();
  354.         }
  355.  
  356.         if( $installed_version && version_compare( SLIDEDECK2_VERSION, $installed_version, '>' ) ) {
  357.             if( version_compare( SLIDEDECK2_VERSION, '2.1', '<' ) ) {
  358.                 if( !class_exists( "SlideDeck" ) ) {
  359.                     include (SLIDEDECK2_DIRNAME . '/classes/slidedeck.php');
  360.                 }
  361.  
  362.                 global $SlideDeckPlugin, $wpdb;
  363.  
  364.                 $SlideDeck = new SlideDeck( );
  365.  
  366.                 $slidedecks = $SlideDeck->get( null, 'post_title', 'ASC', 'publish' );
  367.  
  368.                 foreach( $slidedecks as $slidedeck ) {
  369.                     $sources = $slidedeck['source'];
  370.                     if( !is_array( $sources ) ) {
  371.                         $sources = array( $sources );
  372.                     }
  373.  
  374.                     if( count( $slidedeck['source'] ) > 1 ) {
  375.                         continue;
  376.                     }
  377.  
  378.                     // Update cache duration option name
  379.                     if( isset( $slidedeck['options']['feedCacheDuration'] ) ) {
  380.                         $slidedeck['options']['cache_duration'] = $slidedeck['options']['feedCacheDuration'];
  381.                         unset( $slidedeck['options']['feedCacheDuration'] );
  382.                     }
  383.  
  384.                     // Update Twitter source meta
  385.                     if( in_array( 'twitter', $sources ) ) {
  386.                         $slidedeck['options']['twitter_search_or_user'] = $slidedeck['options']['search_or_user'];
  387.                         unset( $slidedeck['options']['search_or_user'] );
  388.                     }
  389.  
  390.                     // Adjust cache to minutes instead of seconds
  391.                     $intersect = array_intersect( array( 'twitter', 'youtube', 'vimeo', 'dailymotion' ), $sources );
  392.                     if( !empty( $intersect ) ) {
  393.                         $slidedeck['options']['cache_duration'] = round( $slidedeck['options']['cache_duration'] / 60 );
  394.                     }
  395.  
  396.                     update_post_meta( $slidedeck['id'], "slidedeck_options", $slidedeck['options'] );
  397.                 }
  398.             }
  399.  
  400.             // Upgrade to new version
  401.             slidedeck2_km( "SlideDeck Upgraded" );
  402.         }
  403.  
  404.         update_option( "slidedeck_version", SLIDEDECK2_VERSION );
  405.         update_option( "slidedeck_license", SLIDEDECK2_LICENSE );
  406.  
  407.         // Activation
  408.         slidedeck2_km( "SlideDeck Activated" );
  409.     }
  410.  
  411.     /**
  412.      * Add help tab to a page
  413.      *
  414.      * Loads a help file and render's its content to an output buffer, using its
  415.      * content as content
  416.      * for a help tab. Runs the WP_Screen::add_help_tab() method to create a help
  417.      * tab. Returns a boolean
  418.      * value for success of the help addition. Will return boolean(false) if the
  419.      * help file could not
  420.      * be found.
  421.      *
  422.      * @param string $help_id The slug of the help content to get (the name of
  423.      * the help PHP file without the .php extension)
  424.      *
  425.      * @return boolean
  426.      */
  427.     function add_help_tab( $help_id, $title ) {
  428.         $help_filename = SLIDEDECK2_DIRNAME . '/views/help/' . $help_id . '.php';
  429.  
  430.         $success = false;
  431.  
  432.         if( file_exists( $help_filename ) ) {
  433.             // Get the help file's HTML content
  434.             ob_start( );
  435.             include_once ($help_filename);
  436.             $html = ob_get_contents( );
  437.             ob_end_clean( );
  438.  
  439.             get_current_screen( )->add_help_tab( array( 'id' => $help_id, 'title' => __( $title, $this->namespace ), 'content' => $html ) );
  440.  
  441.             $success = true;
  442.         }
  443.  
  444.         return $success;
  445.     }
  446.  
  447.     /**
  448.      * Add in various hooks
  449.      *
  450.      * Place all add_action, add_filter, add_shortcode hook-ins here
  451.      */
  452.     function add_hooks( ) {
  453.         // Upload/Insert Media Buttons
  454.         add_action( 'media_buttons', array( &$this, 'media_buttons' ), 20 );
  455.  
  456.         // Add SlideDeck button to TinyMCE navigation
  457.         add_action( 'admin_init', array( &$this, 'add_tinymce_buttons' ) );
  458.  
  459.         // Options page for configuration
  460.         add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
  461.         add_action( 'admin_menu', array( &$this, 'license_key_check' ) );
  462.  
  463.         // Add JavaScript for pointers
  464.         add_action( 'admin_print_footer_scripts', array( &$this, 'admin_print_footer_scripts' ) );
  465.  
  466.         // Add the JavaScript constants
  467.         add_action( 'admin_print_footer_scripts', array( &$this, 'print_javascript_constants' ) );
  468.         add_action( "{$this->namespace}_print_footer_scripts", array( &$this, 'print_javascript_constants' ) );
  469.         add_action( 'wp_print_footer_scripts', array( &$this, 'print_javascript_constants' ) );
  470.  
  471.         // Add JavaScript and Stylesheets for admin interface on appropriate
  472.         // pages
  473.         add_action( 'admin_print_scripts-slidedeck-2_page_' . SLIDEDECK2_HOOK . '/options', array( &$this, 'admin_print_scripts' ) );
  474.         add_action( 'admin_print_styles-slidedeck-2_page_' . SLIDEDECK2_HOOK . '/options', array( &$this, 'admin_print_styles' ) );
  475.         add_action( 'admin_print_scripts-slidedeck-2_page_' . SLIDEDECK2_HOOK . '/upgrades', array( &$this, 'admin_print_scripts' ) );
  476.         add_action( 'admin_print_styles-slidedeck-2_page_' . SLIDEDECK2_HOOK . '/upgrades', array( &$this, 'admin_print_styles' ) );
  477.         add_action( 'admin_print_scripts-toplevel_page_' . SLIDEDECK2_HOOK, array( &$this, 'admin_print_scripts' ) );
  478.         add_action( 'admin_print_styles-toplevel_page_' . SLIDEDECK2_HOOK, array( &$this, 'admin_print_styles' ) );
  479.         add_action( 'admin_print_scripts-slidedeck-2_page_' . SLIDEDECK2_HOOK . '/lenses', array( &$this, 'admin_print_scripts' ) );
  480.         add_action( 'admin_print_styles-slidedeck-2_page_' . SLIDEDECK2_HOOK . '/lenses', array( &$this, 'admin_print_styles' ) );
  481.  
  482.         // Print editor page only styles
  483.         add_action( 'admin_print_styles', array( &$this, 'admin_print_editor_styles' ) );
  484.  
  485.         // Load IE only stylesheets
  486.         add_action( 'admin_print_styles', array( &$this, 'admin_print_ie_styles' ), 1000 );
  487.  
  488.         // Add custom post type
  489.         add_action( 'init', array( &$this, 'register_post_types' ) );
  490.  
  491.         // Route requests for form processing
  492.         add_action( 'init', array( &$this, 'route' ) );
  493.  
  494.         // Register all JavaScript files used by this plugin
  495.         add_action( 'init', array( &$this, 'wp_register_scripts' ), 1 );
  496.  
  497.         // Register all Stylesheets used by this plugin
  498.         add_action( 'init', array( &$this, 'wp_register_styles' ), 1 );
  499.  
  500.         // Hook into post save to save featured flag and featured title name
  501.         add_action( 'save_post', array( &$this, 'save_post' ) );
  502.  
  503.         add_action( "{$this->namespace}_content_control", array( &$this, 'slidedeck_content_control' ) );
  504.  
  505.         // Add AJAX actions
  506.         add_action( "wp_ajax_{$this->namespace}_add_source", array( &$this, 'ajax_add_source' ) );
  507.         add_action( "wp_ajax_{$this->namespace}_delete_source", array( &$this, 'ajax_delete_source' ) );
  508.         add_action( "wp_ajax_{$this->namespace}_delete_lens_authorize", array( &$this, 'ajax_delete_lens_authorize' ) );
  509.         add_action( "wp_ajax_{$this->namespace}_change_lens", array( &$this, 'ajax_change_lens' ) );
  510.         add_action( "wp_ajax_{$this->namespace}_change_source_view", array( &$this, 'ajax_change_source_view' ) );
  511.         add_action( "wp_ajax_{$this->namespace}_create_new_with_slidedeck", array( &$this, 'ajax_create_new_with_slidedeck' ) );
  512.         add_action( "wp_ajax_{$this->namespace}_covers_modal", array( &$this, 'ajax_covers_modal' ) );
  513.         add_action( "wp_ajax_{$this->namespace}_first_save_dialog", array( &$this, 'ajax_first_save_dialog' ) );
  514.         add_action( "wp_ajax_{$this->namespace}_getcode_dialog", array( &$this, 'ajax_getcode_dialog' ) );
  515.         add_action( "wp_ajax_{$this->namespace}_gplus_posts_how_to_modal", array( &$this, 'ajax_gplus_posts_how_to_modal' ) );
  516.         add_action( "wp_ajax_{$this->namespace}_insert_iframe", array( &$this, 'ajax_insert_iframe' ) );
  517.         add_action( "wp_ajax_{$this->namespace}_insert_iframe_update", array( &$this, 'ajax_insert_iframe_update' ) );
  518.         add_action( "wp_ajax_{$this->namespace}_post_header_redirect", array( &$this, 'ajax_post_header_redirect' ) );
  519.         add_action( "wp_ajax_{$this->namespace}_preview_iframe", array( &$this, 'ajax_preview_iframe' ) );
  520.         add_action( "wp_ajax_nopriv_{$this->namespace}_preview_iframe", array( &$this, 'ajax_preview_iframe' ) );
  521.         add_action( "wp_ajax_{$this->namespace}_preview_iframe_update", array( &$this, 'ajax_preview_iframe_update' ) );
  522.         add_action( "wp_ajax_{$this->namespace}_sort_manage_table", array( &$this, 'ajax_sort_manage_table' ) );
  523.         add_action( "wp_ajax_{$this->namespace}_source_modal", array( &$this, 'ajax_source_modal' ) );
  524.         add_action( "wp_ajax_{$this->namespace}_stage_background", array( &$this, 'ajax_stage_background' ) );
  525.         add_action( "wp_ajax_{$this->namespace}_update_available_lenses", array( &$this, 'ajax_update_available_lenses' ) );
  526.         add_action( "wp_ajax_{$this->namespace}_validate_copy_lens", array( &$this, 'ajax_validate_copy_lens' ) );
  527.         add_action( "wp_ajax_{$this->namespace}_upsell_modal_content", array( &$this, 'ajax_upsell_modal_content' ) );
  528.         add_action( "wp_ajax_{$this->namespace}_verify_license_key", array( &$this, 'ajax_verify_license_key' ) );
  529.         add_action( "wp_ajax_{$this->namespace}_verify_addons_license_key", array( &$this, 'ajax_verify_addons_license_key' ) );
  530.         add_action( "wp_ajax_{$this->namespace}2_blog_feed", array( &$this, 'ajax_blog_feed' ) );
  531.         add_action( "wp_ajax_{$this->namespace}2_tweet_feed", array( &$this, 'ajax_tweet_feed' ) );
  532.  
  533.         // Append necessary lens and initialization script commands to the bottom
  534.         // of the DOM for proper loading
  535.         add_action( 'wp_print_footer_scripts', array( &$this, 'print_footer_scripts' ) );
  536.  
  537.         // Add required JavaScript and Stylesheets for displaying SlideDecks in
  538.         // public view
  539.         add_action( 'wp_print_scripts', array( &$this, 'wp_print_scripts' ) );
  540.        
  541.         // Prints some JavaScript constants in the head tag.
  542.         add_action( 'wp_print_scripts', array( &$this, 'print_header_javascript_constants' ) );
  543.  
  544.         // Front-end only actions
  545.         if( !is_admin( ) ) {
  546.             // Pre-loading for lenses used by SlideDeck(s) in post(s) on a page
  547.             add_action( 'wp', array( &$this, 'wp_hook' ) );
  548.  
  549.             // Print required lens stylesheets
  550.             add_action( 'wp_print_styles', array( &$this, 'wp_print_styles' ) );
  551.         }
  552.  
  553.         add_action( 'update-custom_upload-slidedeck-lens', array( &$this, 'upload_lens' ) );
  554.  
  555.         // Add full screen buttons to post editor
  556.         add_filter( 'wp_fullscreen_buttons', array( &$this, 'wp_fullscreen_buttons' ) );
  557.         // Add a settings link next to the "Deactivate" link on the plugin
  558.         // listing page
  559.         add_filter( 'plugin_action_links', array( &$this, 'plugin_action_links' ), 10, 2 );
  560.        
  561.         add_filter( "{$this->namespace}_sidebar_ad_url", array( &$this, 'slidedeck_sidebar_ad_url' ) );
  562.         add_action( 'slidedeck_manage_sidebar_bottom', array( &$this, 'slidedeck_manage_sidebar_bottom' ) );
  563.         add_filter( "{$this->namespace}_form_content_source", array( &$this, 'slidedeck_form_content_source' ), 10, 2 );
  564.         add_filter( "{$this->namespace}_options_model", array( &$this, 'slidedeck_options_model' ), 9999, 2 );
  565.         add_filter( "{$this->namespace}_options_model", array( &$this, 'slidedeck_options_model_slide_count' ), 5, 2 );
  566.         add_filter( "{$this->namespace}_after_get", array( &$this, 'slidedeck_after_get' ) );
  567.         add_filter( "{$this->namespace}_create_custom_slidedeck_block", array( &$this, 'slidedeck_create_custom_slidedeck_block' ) );
  568.         add_filter( "{$this->namespace}_create_dynamic_slidedeck_block", array( &$this, 'slidedeck_create_dynamic_slidedeck_block' ) );
  569.         add_filter( "{$this->namespace}_lens_selection_after_lenses", array( &$this, 'slidedeck_lens_selection_after_lenses' ) );
  570.         add_filter( "{$this->namespace}_source_modal_after_sources", array( &$this, 'slidedeck_source_modal_after_sources' ) );
  571.  
  572.         // Add shortcode to replace SlideDeck shortcodes in content with
  573.         // SlideDeck contents
  574.         add_shortcode( 'SlideDeck2', array( &$this, 'shortcode' ) );
  575.     }
  576.  
  577.     /**
  578.      * Setup TinyMCE button for fullscreen editor
  579.      *
  580.      * @uses add_filter()
  581.      */
  582.     function add_tinymce_buttons( ) {
  583.         add_filter( 'mce_external_plugins', array( &$this, 'add_tinymce_plugin' ) );
  584.     }
  585.  
  586.     /**
  587.      * Add the SlideDeck TinyMCE plugin to the TinyMCE plugins list
  588.      *
  589.      * @param object $plugin_array The TinyMCE options array
  590.      *
  591.      * @uses slidedeck_is_plugin()
  592.      *
  593.      * @return object $plugin_array The modified TinyMCE options array
  594.      */
  595.     function add_tinymce_plugin( $plugin_array ) {
  596.         if( !$this->is_plugin( ) ) {
  597.             $plugin_array['slidedeck2'] = SLIDEDECK2_URLPATH . '/js/tinymce3/editor-plugin.js';
  598.         }
  599.  
  600.         return $plugin_array;
  601.     }
  602.  
  603.     /**
  604.      * Process update page form submissions
  605.      *
  606.      * @uses slidedeck2_sanitize()
  607.      * @uses wp_redirect()
  608.      * @uses wp_verify_nonce()
  609.      * @uses wp_die()
  610.      * @uses update_option()
  611.      * @uses esc_html()
  612.      * @uses wp_safe_redirect()
  613.      */
  614.     function admin_options_update( ) {
  615.         // Verify submission for processing using wp_nonce
  616.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-update-options" ) )
  617.             wp_die( __( "Unauthorized form submission!", $this->namespace ) );
  618.  
  619.         $data = array( );
  620.         /**
  621.          * Loop through each POSTed value and sanitize it to protect against
  622.          * malicious code. Please
  623.          * note that rich text (or full HTML fields) should not be processed by
  624.          * this function and
  625.          * dealt with directly.
  626.          */
  627.         foreach( $_POST['data'] as $key => $val ) {
  628.             $data[$key] = slidedeck2_sanitize( $val );
  629.         }
  630.  
  631.         // Get the old options
  632.         $old_options = get_option( $this->option_name );
  633.  
  634.         $options = array(
  635.             'disable_wpautop' => isset( $data['disable_wpautop'] ) && !empty( $data['disable_wpautop'] ) ? true : false,
  636.             'dont_enqueue_scrollwheel_library' => isset( $data['dont_enqueue_scrollwheel_library'] ) && !empty( $data['dont_enqueue_scrollwheel_library'] ) ? true : false,
  637.             'dont_enqueue_easing_library' => isset( $data['dont_enqueue_easing_library'] ) && !empty( $data['dont_enqueue_easing_library'] ) ? true : false,
  638.             'disable_edit_create' => isset( $data['disable_edit_create'] ) && !empty( $data['disable_edit_create'] ) ? true : false,
  639.             'twitter_user' => str_replace( "@", "", $data['twitter_user'] ), 'license_key' => $old_options['license_key'],
  640.             'iframe_by_default' => isset( $data['iframe_by_default'] ) && !empty( $data['iframe_by_default'] ) ? true : false,
  641.         );
  642.  
  643.         /**
  644.          * Verify License Key
  645.          */
  646.         $response_json = $this->is_license_key_valid( $data['license_key'] );
  647.         if( $response_json !== false ) {
  648.             if( $response_json->valid == true ) {
  649.                 $options['license_key'] = $data['license_key'];
  650.             }
  651.         } else {
  652.             $options['license_key'] = $data['license_key'];
  653.         }
  654.  
  655.         if( empty( $data['license_key'] ) )
  656.             $options['license_key'] = '';
  657.  
  658.         /**
  659.          * Updating the options that
  660.          * need to be updated by themselves.
  661.          */
  662.         // Update the Instagram Key
  663.         update_option( $this->namespace . '_last_saved_instagram_access_token', slidedeck2_sanitize( $_POST['last_saved_instagram_access_token'] ) );
  664.         // Update the Google+ API  Key
  665.         update_option( $this->namespace . '_last_saved_gplus_api_key', slidedeck2_sanitize( $_POST['last_saved_gplus_api_key'] ) );
  666.  
  667.         /**
  668.          * Updating the options that can be serialized.
  669.          */
  670.         // Update the options value with the data submitted
  671.         update_option( $this->option_name, $options );
  672.  
  673.         slidedeck2_set_flash( "<strong>" . esc_html( __( "Options Successfully Updated", $this->namespace ) ) . "</strong>" );
  674.  
  675.         // Flush WordPress' memory of plugin updates.
  676.         self::check_plugin_updates( );
  677.  
  678.         // Redirect back to the options page with the message flag to show the
  679.         // saved message
  680.         wp_safe_redirect( $_REQUEST['_wp_http_referer'] );
  681.         exit ;
  682.     }
  683.  
  684.     /**
  685.      * Print editor only styles
  686.      */
  687.     function admin_print_editor_styles( ) {
  688.         if( in_array( basename( $_SERVER['PHP_SELF'] ), array( 'post.php', 'post-new.php' ) ) ) {
  689.             include_once (SLIDEDECK2_DIRNAME . '/views/elements/_editor-styles.php');
  690.         }
  691.     }
  692.  
  693.     /**
  694.      * Load footer JavaScript for admin pages
  695.      *
  696.      * @uses SlideDeckPlugin::is_plugin()
  697.      * @uses SlideDeckPointers::render()
  698.      */
  699.     function admin_print_footer_scripts( ) {
  700.         global $wp_scripts, $wp_styles;
  701.  
  702.         if( $this->is_plugin( ) ) {
  703.             $this->Pointers->render( );
  704.         }
  705.  
  706.         // Add target="_blank" to feedback navigation element
  707.         echo '<script type="text/javascript">var feedbacktab=jQuery("#toplevel_page_' . str_replace( ".php", "", SLIDEDECK2_BASENAME ) . '").find(".wp-submenu ul li a[href$=\'/feedback\']").attr("target", "_blank");jQuery(window).load(function(){jQuery("#slidedeck2-submit-ticket").addClass("visible")});</script>';
  708.     }
  709.  
  710.     /**
  711.      * Load JavaScript for the admin options page
  712.      *
  713.      * @uses SlideDeckPlugin::is_plugin()
  714.      * @uses wp_enqueue_script()
  715.      */
  716.     function admin_print_scripts( ) {
  717.         global $wp_scripts;
  718.        
  719.         echo '<script type="text/javascript">var SlideDeckInterfaces = {};</script>';
  720.        
  721.         $wp_scripts->registered["{$this->namespace}-library-js"]->src .= "?noping";
  722.        
  723.         wp_enqueue_script( "{$this->namespace}-library-js" );
  724.         wp_enqueue_script( "{$this->namespace}-admin" );
  725.         wp_enqueue_script( "{$this->namespace}-admin-lite" );
  726.         wp_enqueue_script( "{$this->namespace}-public" );
  727.         wp_enqueue_script( "{$this->namespace}-preview" );
  728.         wp_enqueue_script( 'jquery-ui-core' );
  729.         wp_enqueue_script( 'jquery-ui-sortable' );
  730.         wp_enqueue_script( 'jquery-ui-slider' );
  731.         wp_enqueue_script( 'thickbox' );
  732.         wp_enqueue_script( 'editor' );
  733.         wp_enqueue_script( 'media-upload' );
  734.         wp_enqueue_script( 'quicktags' );
  735.         wp_enqueue_script( 'fancy-form' );
  736.         wp_enqueue_script( 'tooltipper' );
  737.         wp_enqueue_script( 'simplemodal' );
  738.         wp_enqueue_script( 'jquery-minicolors' );
  739.         wp_enqueue_script( 'wp-pointer' );
  740.         wp_enqueue_script( 'zeroclipboard' );
  741.         wp_enqueue_script( 'jquery-masonry' );
  742.     }
  743.  
  744.     /**
  745.      * Load stylesheets for the admin pages
  746.      *
  747.      * @uses wp_enqueue_style()
  748.      * @uses SlideDeckPlugin::is_plugin()
  749.      * @uses SlideDeck::get()
  750.      * @uses SlideDeckPlugin::wp_print_styles()
  751.      */
  752.     function admin_print_styles( ) {
  753.         wp_enqueue_style( "{$this->namespace}-admin" );
  754.         wp_enqueue_style( "{$this->namespace}-admin-lite" );
  755.         wp_enqueue_style( 'thickbox' );
  756.         wp_enqueue_style( 'editor-buttons' );
  757.         wp_enqueue_style( 'fancy-form' );
  758.  
  759.         // Make accommodations for the editing view to only load the lens files
  760.         // for the SlideDeck being edited
  761.         if( $this->is_plugin( ) ) {
  762.             if( isset( $_GET['slidedeck'] ) ) {
  763.                 $slidedeck = $this->SlideDeck->get( $_GET['slidedeck'] );
  764.                 $lens = $slidedeck['lens'];
  765.             } else {
  766.                 $lens = SLIDEDECK2_DEFAULT_LENS;
  767.             }
  768.  
  769.             if( in_array( "gplus", $this->SlideDeck->current_source ) ) {
  770.                 wp_enqueue_style( "gplus-how-to-modal" );
  771.             }
  772.  
  773.             $this->lenses_included = array( $lens => 1 );
  774.         }
  775.  
  776.         if( $this->is_plugin( ) ) {
  777.             wp_enqueue_style( 'wp-pointer' );
  778.             wp_enqueue_style( 'jquery-minicolors' );
  779.         }
  780.  
  781.         // Run the non-admin print styles method to load required lens CSS files
  782.         $this->wp_print_styles( );
  783.     }
  784.  
  785.     /**
  786.      * Load IE only stylesheets for admin pages
  787.      *
  788.      * @uses SlideDeckPlugin::is_plugin()
  789.      */
  790.     function admin_print_ie_styles( ) {
  791.         if( $this->is_plugin( ) ) {
  792.             echo '<!--[if lte IE 8]><link rel="stylesheet" type="text/css" href="' . SLIDEDECK2_URLPATH . '/css/ie.css" /><![endif]-->';
  793.             echo '<!--[if gte IE 9]><link rel="stylesheet" type="text/css" href="' . SLIDEDECK2_URLPATH . '/css/ie9.css" /><![endif]-->';
  794.         }
  795.     }
  796.  
  797.     /**
  798.      * Define the admin menu options for this plugin
  799.      *
  800.      * @uses add_action()
  801.      * @uses add_options_page()
  802.      */
  803.     function admin_menu( ) {
  804.         $show_menu = true;
  805.         if( $this->get_option( 'disable_edit_create' ) == true ) {
  806.             if( !current_user_can( 'manage_options' ) ) {
  807.                 $show_menu = false;
  808.             }
  809.         }
  810.         if( $show_menu === true ) {
  811.             add_menu_page( 'SlideDeck 2', 'SlideDeck 2', 'publish_posts', SLIDEDECK2_BASENAME, array( &$this, 'page_route' ), SLIDEDECK2_URLPATH . '/images/icon.png', 37 );
  812.  
  813.             $this->menu['manage'] = add_submenu_page( SLIDEDECK2_BASENAME, 'Manage SlideDecks', 'Manage', 'publish_posts', SLIDEDECK2_BASENAME, array( &$this, 'page_route' ) );
  814.             $this->menu['lenses'] = add_submenu_page( SLIDEDECK2_BASENAME, 'SlideDeck Lenses', 'Lenses', 'manage_options', SLIDEDECK2_BASENAME . '/lenses', array( &$this, 'page_lenses_route' ) );
  815.             $this->menu['options'] = add_submenu_page( SLIDEDECK2_BASENAME, 'SlideDeck Options', 'Advanced Options', 'manage_options', SLIDEDECK2_BASENAME . '/options', array( &$this, 'page_options' ) );
  816.             $this->menu['upgrades'] = add_submenu_page( SLIDEDECK2_BASENAME, 'SlideDeck Addons', 'SlideDeck Addons', 'manage_options', SLIDEDECK2_BASENAME . '/upgrades', array( &$this, 'page_upgrades' ) );
  817.  
  818.             add_action( "load-{$this->menu['manage']}", array( &$this, "load_admin_page" ) );
  819.             add_action( "load-{$this->menu['lenses']}", array( &$this, "load_admin_page" ) );
  820.             add_action( "load-{$this->menu['options']}", array( &$this, "load_admin_page" ) );
  821.         }
  822.     }
  823.  
  824.     /**
  825.      * AJAX response to adding a source to a SlideDeck
  826.      *
  827.      * Adds a source to a SlideDeck and its preview SlideDeck entry and returns HTML
  828.      * markup for the slide manager area. This method also checks to see if things like
  829.      * the lens need to be changed based off the sources now in the SlideDeck.
  830.      *
  831.      * @uses SlideDeck::add_source()
  832.      * @uses SlideDeck::save_preview()
  833.      * @uses SlideDeckPlugin::get_sources()
  834.      * @uses wp_verify_nonce()
  835.      */
  836.     function ajax_add_source( ) {
  837.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'slidedeck-add-source' ) ) {
  838.             die( "false" );
  839.         }
  840.  
  841.         $namespace = $this->namespace;
  842.         $slidedeck_id = intval( $_REQUEST['slidedeck'] );
  843.        
  844.         // Add source to the parent SlideDeck
  845.         $slidedeck_sources = $this->SlideDeck->add_source( $slidedeck_id, $_REQUEST['source'] );
  846.        
  847.         // Update the preview SlideDeck
  848.         $_REQUEST['source'] = $slidedeck_sources;
  849.         $slidedeck = $this->SlideDeck->save_preview( $slidedeck_id, $_REQUEST );
  850.        
  851.         $default_to_toolkit = false;
  852.        
  853.         // Reset the lens choice to Tool-kit if coming from a Twitter only SlideDeck
  854.         if( $slidedeck['lens'] == "twitter" && (count( $slidedeck_sources ) > 1) ) {
  855.             $default_to_toolkit = true;
  856.         }
  857.        
  858.         // Reset the lens choice to Tool-kit if coming from an all video SlideDeck to a non-all-video SlideDeck
  859.         $all_video_slidedeck = true;
  860.         foreach( $slidedeck_sources as $source ) {
  861.             if( !in_array( $source, array( 'vimeo', 'youtube', 'dailymotion' ) ) ) {
  862.                 $all_video_slidedeck = false;
  863.             }
  864.         }
  865.         if( $slidedeck['lens'] == "video" && $all_video_slidedeck !== true ) {
  866.             $default_to_toolkit = true;
  867.         }
  868.        
  869.         // Update the SlideDeck preview with the Tool-kit lens if needed
  870.         if( $default_to_toolkit == true ) {
  871.             $_REQUEST['lens'] = "tool-kit";
  872.             $slidedeck = $this->SlideDeck->save_preview( $slidedeck_id, $_REQUEST );
  873.         }
  874.        
  875.         // Get all sources models that apply to the updated SlideDeck
  876.         $sources = $this->get_sources( $slidedeck_sources );
  877.         if( isset( $sources['custom'] ) )
  878.             unset( $sources['custom'] );
  879.  
  880.         include (SLIDEDECK2_DIRNAME . '/views/elements/_sources.php');
  881.         exit ;
  882.     }
  883.  
  884.     /**
  885.      * Outputs an <ul> for the SlideDeck Blog on the "Overview" page
  886.      *
  887.      * @uses fetch_feed()
  888.      * @uses wp_redirect()
  889.      * @uses SlideDeckPlugin::action()
  890.      * @uses is_wp_error()
  891.      * @uses SimplePie::get_item_quantity()
  892.      * @uses SimplePie::get_items()
  893.      */
  894.     function ajax_blog_feed( ) {
  895.         if( !SLIDEDECK2_IS_AJAX_REQUEST ) {
  896.             wp_redirect( $this->action( ) );
  897.             exit ;
  898.         }
  899.  
  900.         $rss = fetch_feed( array( 'http://feeds.feedburner.com/Slidedeck', 'http://feeds.feedburner.com/digital-telepathy' ) );
  901.  
  902.         // Checks that the object is created correctly
  903.         if( !is_wp_error( $rss ) ) {
  904.             // Figure out how many total items there are, but limit it to 5.
  905.             $maxitems = $rss->get_item_quantity( 3 );
  906.  
  907.             // Build an array of all the items, starting with element 0 (first
  908.             // element).
  909.             $rss_items = $rss->get_items( 0, $maxitems );
  910.  
  911.             include (SLIDEDECK2_DIRNAME . '/views/elements/_blog-feed.php');
  912.             exit ;
  913.         }
  914.  
  915.         die( "Could not connect to SlideDeck blog feed..." );
  916.     }
  917.  
  918.     /**
  919.      * AJAX response for an updated list of available lenses to a SlideDeck
  920.      *
  921.      * Looks up available lenses for a SlideDeck and returns the markup to update
  922.      * the Lens options group.
  923.      *
  924.      * @uses SlideDeckPlugin::get_slidedeck_lenses()
  925.      */
  926.     function ajax_update_available_lenses( ) {
  927.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-update-available-lenses" ) ) {
  928.             wp_die( __( "You are not authorized to do that.", $this->namespace ) );
  929.         }
  930.  
  931.         $slidedeck_id = intval( $_REQUEST['slidedeck_id'] );
  932.         $slidedeck_preview_id = $this->SlideDeck->get_preview_id( $slidedeck_id );
  933.         $slidedeck = $this->SlideDeck->get( $slidedeck_preview_id );
  934.         $this->SlideDeck->current_source = $slidedeck['source'];
  935.         $lenses = $this->get_slidedeck_lenses( $slidedeck );
  936.  
  937.         include (SLIDEDECK2_DIRNAME . '/views/elements/_options-lenses.php');
  938.         exit ;
  939.     }
  940.  
  941.     /**
  942.      * Outputs SlideDeck Markup for the latest tweets deck
  943.      *
  944.      * @uses fetch_feed()
  945.      * @uses wp_redirect()
  946.      * @uses SlideDeckPlugin::action()
  947.      * @uses is_wp_error()
  948.      * @uses SimplePie::get_item_quantity()
  949.      * @uses SimplePie::get_items()
  950.      */
  951.     function ajax_tweet_feed( ) {
  952.         if( !SLIDEDECK2_IS_AJAX_REQUEST ) {
  953.             wp_redirect( $this->action( ) );
  954.             exit ;
  955.         }
  956.  
  957.         // Combines the dt and sd feeds:
  958.         $rss = fetch_feed( array( 'http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=slidedeck', 'http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=dtelepathy', ) );
  959.  
  960.         // Checks that the object is created correctly
  961.         if( !is_wp_error( $rss ) ) {
  962.             // Figure out how many total items there are, but limit it to 5.
  963.             $maxitems = $rss->get_item_quantity( 5 );
  964.  
  965.             // Build an array of all the items, starting with element 0 (first
  966.             // element).
  967.             $rss_items = $rss->get_items( 0, $maxitems );
  968.  
  969.             $url_regex = '/((https?|ftp|gopher|telnet|file|notes|ms-help):((\/\/)|(\\\\))+[\w\d:#@%\/\;$()~_?\+-=\\\.&]*)/';
  970.             $formatted_rss_items = array( );
  971.             foreach( $rss_items as $key => $value ) {
  972.                 $tweet = $value->get_title( );
  973.  
  974.                 // Remove the 'dtelepathy: ' part at the beginning of the feed:
  975.                 $tweet = preg_replace( '/^[^\s]+:\s/', '', $tweet );
  976.                 // Link all the links:
  977.                 $tweet = preg_replace( $url_regex, '<a href="$1" target="_blank">' . "$1" . '</a>', $tweet );
  978.                 // Link the hashtags and mentions
  979.                 $tweet = preg_replace( array( '/\@([a-zA-Z0-9_]+)/', # Twitter
  980.                # Usernames
  981.                '/\#([a-zA-Z0-9_]+)/' # Hash Tags
  982.                ), array( '<a href="http://twitter.com/$1" target="_blank">@$1</a>', '<a href="http://twitter.com/search?q=%23$1" target="_blank">#$1</a>' ), $tweet );
  983.  
  984.                 $formatted_rss_items[] = array( 'tweet' => $tweet, 'time_ago' => human_time_diff( strtotime( $value->get_date( ) ), current_time( 'timestamp' ) ) . " ago", 'permalink' => $value->get_permalink( ) );
  985.             }
  986.  
  987.             include (SLIDEDECK2_DIRNAME . '/views/elements/_latest-tweets.php');
  988.             exit ;
  989.         }
  990.  
  991.         die( "Could not connect to Twitter..." );
  992.     }
  993.  
  994.     /**
  995.      * Change Lens for the current SlideDeck
  996.      *
  997.      * @uses wp_verify_nonce()
  998.      * @uses SlideDeckPlugin::_save_autodraft()
  999.      * @uses apply_filters()
  1000.      */
  1001.     function ajax_change_lens( ) {
  1002.         // Fail silently if the request could not be verified
  1003.         if( !wp_verify_nonce( $_REQUEST['_wpnonce_lens_update'], 'slidedeck-lens-update' ) ) {
  1004.             die( "false" );
  1005.         }
  1006.  
  1007.         $namespace = $this->namespace;
  1008.  
  1009.         $slidedeck_id = intval( $_REQUEST['id'] );
  1010.         $response = $this->_save_autodraft( $slidedeck_id, $_REQUEST );
  1011.  
  1012.         $slidedeck = $response['preview'];
  1013.  
  1014.         $options_model = $this->get_options_model( $slidedeck );
  1015.  
  1016.         $lenses = $this->get_slidedeck_lenses( $slidedeck );
  1017.  
  1018.         $lens = $this->Lens->get( $slidedeck['lens'] );
  1019.         $lens_classname = slidedeck2_get_classname_from_filename( $slidedeck['lens'] );
  1020.         $response['lens'] = $lens;
  1021.        
  1022.         // If this Lens has an options model, loop through it and set the new
  1023.         // defaults
  1024.         if( isset( $this->lenses[$lens_classname]->options_model ) ) {
  1025.             $lens_options_model = $this->lenses[$lens_classname]->options_model;
  1026.             // Loop through Lens' option groups
  1027.             foreach( $lens_options_model as $lens_options_group => $lens_group_options ) {
  1028.                 // Loop through Lens' option group options
  1029.                 foreach( $lens_group_options as $name => $properties ) {
  1030.                     // If the filtered options model has a value set, use it as
  1031.                     // an override to the saved value
  1032.                     if( isset( $options_model[$lens_options_group][$name]['value'] ) )
  1033.                         $slidedeck['options'][$name] = $options_model[$lens_options_group][$name]['value'];
  1034.                 }
  1035.             }
  1036.         }
  1037.  
  1038.         $response['sizes'] = apply_filters( "{$this->namespace}_sizes", $this->sizes, $slidedeck );
  1039.  
  1040.         uksort( $options_model['Appearance']['titleFont']['values'], 'strnatcasecmp' );
  1041.         uksort( $options_model['Appearance']['bodyFont']['values'], 'strnatcasecmp' );
  1042.  
  1043.         // Trim out the Setup key
  1044.         $trimmed_options_model = $options_model;
  1045.         unset( $trimmed_options_model['Setup'] );
  1046.         $options_groups = $this->options_model_groups;
  1047.  
  1048.         $sizes = apply_filters( "{$this->namespace}_sizes", $this->sizes, $slidedeck );
  1049.  
  1050.         ob_start( );
  1051.         include (SLIDEDECK2_DIRNAME . '/views/elements/_options.php');
  1052.         $response['options_html'] = ob_get_contents( );
  1053.         ob_end_clean( );
  1054.        
  1055.         die( json_encode( $response ) );
  1056.     }
  1057.  
  1058.     /**
  1059.      * AJAX response for Covers edit modal
  1060.      */
  1061.     function ajax_covers_modal( ) {
  1062.         if( !class_exists( 'SlideDeckCovers' ) )
  1063.             return false;
  1064.        
  1065.         global $slidedeck_fonts;
  1066.  
  1067.         $slidedeck_id = $_REQUEST['slidedeck'];
  1068.  
  1069.         $slidedeck = $this->SlideDeck->get( $slidedeck_id );
  1070.         $cover = $this->Cover->get( $slidedeck_id );
  1071.  
  1072.         $dimensions = $this->SlideDeck->get_dimensions( $slidedeck );
  1073.         $scaleRatio = 516 / $dimensions['outer_width'];
  1074.         if( $scaleRatio > 1 )
  1075.             $scaleRatio = 1;
  1076.  
  1077.         $size_class = $slidedeck['options']['size'];
  1078.         if( $slidedeck['options']['size'] == "custom" ) {
  1079.             $size_class = $this->SlideDeck->get_closest_size( $slidedeck );
  1080.         }
  1081.  
  1082.         $namespace = $this->namespace;
  1083.  
  1084.         $cover_options_model = $this->Cover->options_model;
  1085.  
  1086.         // Options for both front and back covers
  1087.         $global_options = array( 'title_font', 'accent_color', 'cover_style', 'variation', 'peek' );
  1088.         // Front cover options
  1089.         $front_options = array( 'front_title', 'show_curator' );
  1090.         // Back cover options
  1091.         $back_options = array( 'back_title', 'button_label', 'button_url' );
  1092.  
  1093.         $variations = $this->Cover->variations;
  1094.         $cover_options_model['variation']['values'] = $variations[$cover['cover_style']];
  1095.  
  1096.         include (SLIDEDECK2_DIRNAME . '/views/cover-modal.php');
  1097.         exit ;
  1098.     }
  1099.  
  1100.     /**
  1101.      * Create a new post/page with a SlideDeck
  1102.      *
  1103.      * @uses admin_url()
  1104.      * @uses current_user_can()
  1105.      * @uses get_post_type_object()
  1106.      * @uses wp_die()
  1107.      * @uses wp_insert_post()
  1108.      * @uses wp_redirect()
  1109.      */
  1110.     function ajax_create_new_with_slidedeck( ) {
  1111.         // Allowed post types to start with a SlideDeck
  1112.         $acceptable_post_types = array( 'post', 'page' );
  1113.         $post_type = in_array( $_REQUEST['post_type'], $acceptable_post_types ) ? $_REQUEST['post_type'] : 'post';
  1114.  
  1115.         // Get the post type object
  1116.         $post_type_object = get_post_type_object( $post_type );
  1117.  
  1118.         // Make sure the user can actually edit this post type, if not fail
  1119.         if( !current_user_can( $post_type_object->cap->edit_posts ) )
  1120.             wp_die( __( "You are not authorized to do that", $this->namespace ) );
  1121.  
  1122.         $slidedeck_id = intval( $_REQUEST['slidedeck'] );
  1123.  
  1124.         $params = array( 'post_type' => $post_type, 'post_status' => 'auto-draft', 'post_title' => "", 'post_content' => "<p>" . $this->get_slidedeck_shortcode( $slidedeck_id ) . "</p>" );
  1125.  
  1126.         $new_post_id = wp_insert_post( $params );
  1127.  
  1128.         wp_redirect( admin_url( 'post.php?post=' . $new_post_id . '&action=edit' ) );
  1129.         exit ;
  1130.     }
  1131.  
  1132.     /**
  1133.      * Delete a SlideDeck
  1134.      *
  1135.      * AJAX response for deletion of a SlideDeck
  1136.      *
  1137.      * @uses wp_verify_nonce()
  1138.      * @uses wp_delete_post()
  1139.      * @uses SlideDeckPlugin::load_slides()
  1140.      * @uses wp_remote_fopen()
  1141.      */
  1142.     function ajax_delete( ) {
  1143.         if( !SLIDEDECK2_IS_AJAX_REQUEST ) {
  1144.             wp_redirect( $this->action( ) );
  1145.             exit ;
  1146.         }
  1147.  
  1148.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-delete-slidedeck" ) ) {
  1149.             die( "false" );
  1150.         }
  1151.  
  1152.         $slidedeck_id = $_REQUEST['slidedeck'];
  1153.  
  1154.         $this->SlideDeck->delete( $slidedeck_id );
  1155.  
  1156.         $redirect = $this->action( ) . "&msg_deleted=1";
  1157.  
  1158.         slidedeck2_km( "SlideDeck Deleted" );
  1159.  
  1160.         die( $redirect );
  1161.     }
  1162.  
  1163.     /**
  1164.      * Duplicate a SlideDeck
  1165.      *
  1166.      * AJAX response for duplication of a SlideDeck
  1167.      *
  1168.      * @uses wp_verify_nonce()
  1169.      */
  1170.     function ajax_duplicate( ) {
  1171.         if( !SLIDEDECK2_IS_AJAX_REQUEST ) {
  1172.             wp_redirect( $this->action( ) );
  1173.             exit ;
  1174.         }
  1175.  
  1176.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-duplicate-slidedeck" ) ) {
  1177.             die( "false" );
  1178.         }
  1179.  
  1180.         $slidedeck_id = $_REQUEST['slidedeck'];
  1181.         $this->SlideDeck->duplicate_slidedeck( $slidedeck_id );
  1182.  
  1183.         // Grab the order from the saved option value
  1184.         $orderby = get_option( "{$this->namespace}_manage_table_sort" );
  1185.         $order = $orderby == 'post_modified' ? 'DESC' : 'ASC';
  1186.  
  1187.         $namespace = $this->namespace;
  1188.         $slidedecks = $this->SlideDeck->get( null, $orderby, $order, 'publish' );
  1189.  
  1190.         include (SLIDEDECK2_DIRNAME . '/views/elements/_manage-table.php');
  1191.  
  1192.         slidedeck2_km( "SlideDeck Duplicated" );
  1193.         exit ;
  1194.     }
  1195.  
  1196.     /**
  1197.      * Delete a lens
  1198.      *
  1199.      * AJAX response for deleting a SlideDeck lens
  1200.      *
  1201.      * @uses SlideDeckLens::delete()
  1202.      */
  1203.     function ajax_delete_lens( ) {
  1204.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-delete-lens" ) ) {
  1205.             die( "false" );
  1206.         }
  1207.  
  1208.         header( "Content Type: application/json" );
  1209.  
  1210.  
  1211.         $data = slidedeck2_sanitize( $_POST );
  1212.         $response = array( 'message' => "Lens deleted successfuly", 'error' => false );
  1213.        
  1214.         if( !current_user_can( 'delete_themes' ) ) {
  1215.             $response['message'] = "Sorry, your user does not have permission to delete a lens";
  1216.             $response['error'] = true;
  1217.             die( json_encode( $response ) );
  1218.         }
  1219.  
  1220.         if( !isset( $data['lens'] ) ) {
  1221.             $response['message'] = "No lens was specified";
  1222.             $response['error'] = true;
  1223.             die( json_encode( $response ) );
  1224.         }
  1225.  
  1226.         if( !$response['error'] ) {
  1227.             $lens = $this->Lens->delete( $data['lens'] );
  1228.             if( $lens == false ) {
  1229.                 $response['message'] = "Folder could not be deleted, please make sure the server can delete this folder";
  1230.                 $response['error'] = true;
  1231.                 $response['redirect'] = $this->action( '/lenses' ) . '&action=delete_authorize&lens=' . $data['lens'] . '&_wpnonce=' . wp_create_nonce( $this->namespace . '-delete-lens-authorize' );
  1232.             }
  1233.         }
  1234.  
  1235.         die( json_encode( $response ) );
  1236.     }
  1237.        
  1238.     /**
  1239.      * Delete a source
  1240.      *
  1241.      * AJAX response for deleting a SlideDeck source from a multi-source
  1242.      * dynamic SlideDeck.
  1243.      */
  1244.     function ajax_delete_source( ) {
  1245.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-delete-source" ) ) {
  1246.             die( "false" );
  1247.         }
  1248.  
  1249.         if( !isset( $_REQUEST['slidedeck'] ) ) {
  1250.             die( "false" );
  1251.         }
  1252.  
  1253.         $namespace = $this->namespace;
  1254.         $source = $_REQUEST['source'];
  1255.         $slidedeck_id = intval( $_REQUEST['slidedeck'] );
  1256.  
  1257.         $this->SlideDeck->delete_source( $slidedeck_id, $source );
  1258.         $slidedeck_preview_id = $this->SlideDeck->get_preview_id( $slidedeck_id );
  1259.         $slidedeck = $this->SlideDeck->get( $slidedeck_preview_id );
  1260.  
  1261.         $sources = $this->get_sources( $slidedeck['source'] );
  1262.         if( isset( $sources['custom'] ) )
  1263.             unset( $sources['custom'] );
  1264.  
  1265.         include (SLIDEDECK2_DIRNAME . '/views/elements/_sources.php');
  1266.         exit ;
  1267.     }
  1268.  
  1269.     /**
  1270.      * First save dialog box
  1271.      *
  1272.      * AJAX response for display of first save dialog box
  1273.      *
  1274.      * @uses SlideDeck::get()
  1275.      */
  1276.     function ajax_first_save_dialog( ) {
  1277.         $slidedeck_id = intval( $_REQUEST['slidedeck'] );
  1278.         $slidedeck = $this->SlideDeck->get( $slidedeck_id );
  1279.         $namespace = $this->namespace;
  1280.  
  1281.         $iframe_by_default = $this->get_option( 'iframe_by_default' );
  1282.  
  1283.         include (SLIDEDECK2_DIRNAME . '/views/first-save-dialog.php');
  1284.         exit ;
  1285.     }
  1286.  
  1287.     /**
  1288.      * Get code dialog box
  1289.      *
  1290.      * AJAX response for display of get code dialog box
  1291.      *
  1292.      * @uses SlideDeck::get()
  1293.      */
  1294.     function ajax_getcode_dialog( ) {
  1295.         $slidedeck_id = intval( $_REQUEST['slidedeck'] );
  1296.         $slidedeck = $this->SlideDeck->get( $slidedeck_id );
  1297.         $namespace = $this->namespace;
  1298.        
  1299.         $iframe_by_default = $this->get_option( 'iframe_by_default' );
  1300.  
  1301.         include (SLIDEDECK2_DIRNAME . '/views/getcode-dialog.php');
  1302.         exit ;
  1303.     }
  1304.  
  1305.     /**
  1306.      * Google+ Posts How to Modal
  1307.      *
  1308.      * AJAX response for Google+ Posts How to Modal
  1309.      */
  1310.     function ajax_gplus_posts_how_to_modal( ) {
  1311.         $namespace = $this->namespace;
  1312.  
  1313.         include (SLIDEDECK2_DIRNAME . '/views/gplus-posts-how-to.php');
  1314.         exit ;
  1315.     }
  1316.  
  1317.     /**
  1318.      * Insert SlideDeck iframe
  1319.      *
  1320.      * Generates a list of SlidDecks available to insert into a post
  1321.      *
  1322.      * @global $wp_scripts
  1323.      *
  1324.      * @uses SlideDeckPlugin::get_insert_iframe_table()
  1325.      */
  1326.     function ajax_insert_iframe( ) {
  1327.         global $wp_scripts;
  1328.  
  1329.         $order_options = $this->order_options;
  1330.         $orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : get_option( "{$this->namespace}_manage_table_sort", reset( array_keys( $this->order_options ) ) );
  1331.  
  1332.         $namespace = $this->namespace;
  1333.         $previous_slidedeck_type = "";
  1334.  
  1335.         $insert_iframe_table = $this->get_insert_iframe_table( $orderby );
  1336.  
  1337.         include (SLIDEDECK2_DIRNAME . '/views/insert-iframe.php');
  1338.         exit ;
  1339.     }
  1340.  
  1341.     /**
  1342.      * AJAX update of Insert SlideDeck iframe table
  1343.      *
  1344.      * Changes the ordering of the SlideDecks in the insert table
  1345.      *
  1346.      * @uses wp_verify_nonce()
  1347.      * @uses wp_die()
  1348.      * @uses SlideDeckPlugin::get_insert_iframe_table()
  1349.      */
  1350.     function ajax_insert_iframe_update( ) {
  1351.         if( !wp_verify_nonce( $_REQUEST['_wpnonce_insert_update'], "slidedeck-update-insert-iframe" ) )
  1352.             wp_die( __( "Unauthorized form submission!", $this->namespace ) );
  1353.  
  1354.         $selected = isset( $_REQUEST['slidedecks'] ) ? $_REQUEST['slidedecks'] : array( );
  1355.  
  1356.         $insert_iframe_table = $this->get_insert_iframe_table( $_REQUEST['orderby'], (array)$selected );
  1357.  
  1358.         die( $insert_iframe_table );
  1359.     }
  1360.  
  1361.     /**
  1362.      * AJAX response for post header redirect
  1363.      *
  1364.      * @uses wp_verify_nonce()
  1365.      */
  1366.     function ajax_post_header_redirect( ) {
  1367.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-post-header-redirect" ) ) {
  1368.             wp_die( "You do not have access to this URL" );
  1369.         }
  1370.  
  1371.         $location = $_REQUEST['location'];
  1372.  
  1373.         $message = "";
  1374.         if( isset( $_REQUEST['message'] ) ) {
  1375.             $message = urldecode( $_REQUEST['message'] );
  1376.             slidedeck2_set_flash( $message, true );
  1377.         }
  1378.  
  1379.         wp_redirect( $location );
  1380.         exit ;
  1381.     }
  1382.  
  1383.     /**
  1384.      * AJAX function for previewing a SlideDeck in an iframe
  1385.      *
  1386.      * @param int $_GET['slidedeck_id'] The ID of the SlideDeck to load
  1387.      * @param int $_GET['width'] The width of the preview window
  1388.      * @param int $_GET['height'] The height of the preview window
  1389.      * @param int $_GET['outer_width'] The width of the SlideDeck in the preview
  1390.      * window
  1391.      * @param int $_GET['outer_height'] The height of the SlideDeck in the
  1392.      * preview window
  1393.      *
  1394.      * @return the preview window as templated in views/preview-iframe.php
  1395.      */
  1396.     function ajax_preview_iframe( ) {
  1397.         global $wp_scripts, $wp_styles;
  1398.  
  1399.         $slidedeck_id = $_GET['slidedeck'];
  1400.         // $width = $_GET['width'];
  1401.         // $height = $_GET['height'];
  1402.         if( isset( $_GET['outer_width'] ) && is_numeric( $_GET['outer_width'] ) )
  1403.             $outer_width = $_GET['outer_width'];
  1404.         // $outer_height = $_GET['outer_height'];
  1405.  
  1406.         $slidedeck = $this->SlideDeck->get( $slidedeck_id );
  1407.  
  1408.         $lens = $this->Lens->get( $slidedeck['lens'] );
  1409.        
  1410.         // Is this a preview or an iframe=1 shortcode embed?
  1411.         $preview = false;
  1412.         if( isset( $_GET['preview'] ) ) {
  1413.             if( (int) $_GET['preview'] === 1 ) {
  1414.                 $preview = true;
  1415.             }
  1416.         }
  1417.        
  1418.         $namespace = $this->namespace;
  1419.  
  1420.         if( isset( $outer_width ) ) {
  1421.             $preview_scale_ratio = $outer_width / 347;
  1422.             $preview_font_size = intval( min( $preview_scale_ratio * 1000, 1139 ) ) / 1000;
  1423.         }
  1424.        
  1425.         $scripts = apply_filters( "{$this->namespace}_iframe_scripts", array( 'jquery', 'jquery-easing', 'scrolling-js', 'slidedeck-library-js', 'slidedeck-public' ), $slidedeck );
  1426.  
  1427.         $content_url = defined( 'WP_CONTENT_URL' ) ? WP_CONTENT_URL : '';
  1428.         $base_url = !site_url( ) ? wp_guess_url( ) : site_url( );
  1429.  
  1430.         include (SLIDEDECK2_DIRNAME . '/views/preview-iframe.php');
  1431.         exit ;
  1432.     }
  1433.  
  1434.     /**
  1435.      * AJAX function for getting a new preview URL in an iframe
  1436.      *
  1437.      * Saves an auto-draft of the SlideDeck being worked on and renders a JSON
  1438.      * response
  1439.      * with the URL to update the preview iframe, showing the auto-draft values.
  1440.      */
  1441.     function ajax_preview_iframe_update( ) {
  1442.         // Fail silently if the request could not be verified
  1443.         if( !wp_verify_nonce( $_REQUEST['_wpnonce_preview'], 'slidedeck-preview-iframe-update' ) ) {
  1444.             die( "false" );
  1445.         }
  1446.  
  1447.         // Parent SlideDeck ID
  1448.         $slidedeck_id = intval( $_REQUEST['id'] );
  1449.         $response = $this->_save_autodraft( $slidedeck_id, $_REQUEST );
  1450.  
  1451.         die( json_encode( $response ) );
  1452.     }
  1453.  
  1454.     /**
  1455.      * AJAX sort of manage table
  1456.      *
  1457.      * AJAX response to change sort of the manage view table of the user's
  1458.      * SlideDecks.
  1459.      * Updates the chosen sort method as well and uses it here and the insert
  1460.      * modal.
  1461.      *
  1462.      * @uses wp_verify_nonce()
  1463.      * @uses SlideDeck::get()
  1464.      * @uses update_option()
  1465.      */
  1466.     function ajax_sort_manage_table( ) {
  1467.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'slidedeck-sort-manage-table' ) ) {
  1468.             die( "false" );
  1469.         }
  1470.  
  1471.         $orderby = in_array( $_REQUEST['orderby'], array_keys( $this->order_options ) ) ? $_REQUEST['orderby'] : reset( array_keys( $this->order_options ) );
  1472.         $order = $orderby == 'post_modified' ? 'DESC' : 'ASC';
  1473.  
  1474.         $namespace = $this->namespace;
  1475.         $slidedecks = $this->SlideDeck->get( null, $orderby, $order, 'publish' );
  1476.  
  1477.         update_option( "{$this->namespace}_manage_table_sort", $orderby );
  1478.  
  1479.         include (SLIDEDECK2_DIRNAME . '/views/elements/_manage-table.php');
  1480.         exit ;
  1481.     }
  1482.  
  1483.     /**
  1484.      * AJAX function for the source choice modal
  1485.      *
  1486.      * @uses wp_verify_nonce()
  1487.      */
  1488.     function ajax_source_modal( ) {
  1489.         // Fail silently if the request could not be verified
  1490.         if( !wp_verify_nonce( $_REQUEST['_wpnonce_source_modal'], 'slidedeck-source-modal' ) ) {
  1491.             die( "false" );
  1492.         }
  1493.  
  1494.         $sources = $this->get_sources( );
  1495.         if( isset( $sources['custom'] ) )
  1496.             unset( $sources['custom'] );
  1497.  
  1498.         $namespace = $this->namespace;
  1499.         $title = "Choose a source to get started";
  1500.         $action = "create";
  1501.         $disabled_sources = array( );
  1502.         $slidedeck_id = 0;
  1503.  
  1504.         if( isset( $_REQUEST['slidedeck'] ) && !empty( $_REQUEST['slidedeck'] ) ) {
  1505.             $action = "{$this->namespace}_add_source";
  1506.             $title = "Choose an additional content source";
  1507.             $slidedeck_id = intval( $_REQUEST['slidedeck'] );
  1508.  
  1509.             $slidedeck = $this->SlideDeck->get( $slidedeck_id );
  1510.             $disabled_sources = $slidedeck['source'];
  1511.         }
  1512.  
  1513.         include (SLIDEDECK2_DIRNAME . '/views/elements/_source-modal.php');
  1514.         exit ;
  1515.     }
  1516.  
  1517.     /**
  1518.      * AJAX response to save stage background preferences
  1519.      *
  1520.      * @global $current_user
  1521.      *
  1522.      * @uses get_currentuserinfo()
  1523.      * @uses wp_verify_nonce()
  1524.      * @uses update_post_meta()
  1525.      * @uses update_user_meta()
  1526.      */
  1527.     function ajax_stage_background( ) {
  1528.         global $current_user;
  1529.         get_currentuserinfo( );
  1530.  
  1531.         // Fail silently if not authorized
  1532.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-stage-background" ) ) {
  1533.             exit ;
  1534.         }
  1535.  
  1536.         $slidedeck_id = intval( $_POST['slidedeck'] );
  1537.  
  1538.         if( in_array( $_POST['background'], array_keys( $this->stage_backgrounds ) ) ) {
  1539.             update_post_meta( $slidedeck_id, "{$this->namespace}_stage_background", $_POST['background'] );
  1540.             update_user_meta( $current_user->ID, "{$this->namespace}_default_stage_background", $_POST['background'] );
  1541.         }
  1542.     }
  1543.  
  1544.     /**
  1545.      * AJAX response to upsell modal
  1546.      */
  1547.     function ajax_upsell_modal_content() {
  1548.         include( SLIDEDECK2_DIRNAME . '/views/upsells/_upsell-modal-' . $_REQUEST['feature'] . '.php' );
  1549.         exit;
  1550.     }
  1551.  
  1552.     /**
  1553.      * AJAX response to validate a lens for copying
  1554.      *
  1555.      * @uses slidedeck2_sanitize()
  1556.      * @uses SlideDeckLens::get()
  1557.      */
  1558.     function ajax_validate_copy_lens( ) {
  1559.         header( "Content Type: application/json" );
  1560.  
  1561.         $data = slidedeck2_sanitize( $_REQUEST );
  1562.         $response = array( 'valid' => true );
  1563.  
  1564.         if( !isset( $data['slug'] ) ) {
  1565.             $response['valid'] = false;
  1566.         }
  1567.  
  1568.         if( $response['valid'] !== false ) {
  1569.             $lens = $this->Lens->get( $data['slug'] );
  1570.  
  1571.             if( $lens !== false ) {
  1572.                 $response['valid'] = false;
  1573.             }
  1574.         }
  1575.  
  1576.         die( json_encode( $response ) );
  1577.     }
  1578.  
  1579.     /**
  1580.      * Ajax Verify License Key
  1581.      *
  1582.      * This function sends a request to the license server and
  1583.      * attempts to get a status on the license key in question.
  1584.      *
  1585.      * @uses wp_verify_nonce()
  1586.      *
  1587.      * @return string
  1588.      */
  1589.     function ajax_verify_license_key( ) {
  1590.         if( !wp_verify_nonce( $_REQUEST['verify_license_nonce'], "{$this->namespace}_verify_license_key" ) )
  1591.             wp_die( __( "Unauthorized request!", $this->namespace ) );
  1592.  
  1593.         $key = $_REQUEST['key'];
  1594.  
  1595.         $response_json = $this->is_license_key_valid( $key );
  1596.  
  1597.         if( $response_json !== false ) {
  1598.             if( $response_json->valid == true ) {
  1599.                 // If the response is true, we save the key.
  1600.  
  1601.                 // Get the options and then save em.
  1602.                 $options = get_option( $this->option_name );
  1603.                 $options['license_key'] = $key;
  1604.                 update_option( $this->option_name, $options );
  1605.  
  1606.             }
  1607.             echo $response_json->message;
  1608.         } else {
  1609.             echo 'Connection error';
  1610.         }
  1611.         exit ;
  1612.     }
  1613.  
  1614.     /**
  1615.      * Ajax Verify Addon License Key
  1616.      *
  1617.      * This function sends a request to the license server and
  1618.      * attempts to get a status on the license key in question and
  1619.      * the installation buttons for the addons purchased
  1620.      *
  1621.      * @uses wp_verify_nonce()
  1622.      * @uses $this->is_license_key_valid()
  1623.      *
  1624.      * @return string
  1625.      */
  1626.     function ajax_verify_addons_license_key( ) {
  1627.         if( !wp_verify_nonce( $_REQUEST['verify_addons_nonce'], "{$this->namespace}_verify_addons_license_key" ) )
  1628.             wp_die( __( "Unauthorized request!", $this->namespace ) );
  1629.  
  1630.         $license_key = $_REQUEST['data']['license_key'];
  1631.         $install_link = false;
  1632.         $installable_addons = false;
  1633.         $cohort_data = self::get_cohort_data();
  1634.        
  1635.         // Save the key if it's valid.
  1636.         // TODO: Maybe refactor...
  1637.         if( !empty( $license_key ) ){
  1638.             $response_json = $this->is_license_key_valid( $license_key );
  1639.    
  1640.             if( $response_json !== false ) {
  1641.                 if( $response_json->valid == true ) {
  1642.                     // If the response is true, we save the key.
  1643.    
  1644.                     // Get the options and then save em.
  1645.                     $options = get_option( $this->option_name );
  1646.                     $options['license_key'] = $license_key;
  1647.                     update_option( $this->option_name, $options );
  1648.                 }
  1649.             }
  1650.         }
  1651.        
  1652.  
  1653.         if( isset( $_REQUEST['imback'] ) && $_REQUEST['imback'] === 'true' )
  1654.             $this->user_is_back = true;
  1655.  
  1656.         if( isset( $_REQUEST['tier'] ) && !empty( $_REQUEST['tier'] ) )
  1657.             $this->upgraded_to_tier = intval( $_REQUEST['tier'] );
  1658.  
  1659.         $response = wp_remote_post( SLIDEDECK2_UPDATE_SITE . '/available-addons', array(
  1660.                 'method' => 'POST',
  1661.                 'timeout' => 4,
  1662.                 'redirection' => 5,
  1663.                 'httpversion' => '1.0',
  1664.                 'blocking' => true,
  1665.                 'headers' => array(
  1666.                     'SlideDeck-Version' => SLIDEDECK2_VERSION,
  1667.                     'User-Agent' => 'WordPress/' . get_bloginfo("version"),
  1668.                     'Referer' => get_bloginfo("url"),
  1669.                     'Addons' => '1'
  1670.                 ),
  1671.                 'body' => array(
  1672.                     'key' => md5( $license_key ),
  1673.                     'redirect_after' => urlencode( admin_url( '/admin.php?page=' . basename( SLIDEDECK2_BASENAME ) ) ),
  1674.                     'installed_addons' => SlideDeckLitePlugin::$addons_installed,
  1675.                     'user_is_back' => $this->user_is_back,
  1676.                     'upgraded_to_tier' => $this->upgraded_to_tier,
  1677.                     'cohort_data' => $cohort_data,
  1678.                 ),
  1679.                 'cookies' => array(),
  1680.                 'sslverify' => false
  1681.             )
  1682.         );
  1683.         if( !is_wp_error( $response ) ) {
  1684.             //echo json_decode( $response['body'], true );
  1685.             echo $response['body'];
  1686.         }
  1687.         exit;
  1688.     }
  1689.  
  1690.     /**
  1691.      * Is Key Vaild?
  1692.      *
  1693.      * @return object Response Object
  1694.      */
  1695.     function is_license_key_valid( $key ) {
  1696.         $key = slidedeck2_sanitize( $key );
  1697.         $upgrade_url = SLIDEDECK2_UPDATE_SITE . '/wordpress-update/' . md5( $key );
  1698.        
  1699.         $response = wp_remote_post( $upgrade_url, array( 'method' => 'POST', 'timeout' => 4, 'redirection' => 5, 'httpversion' => '1.0', 'blocking' => true, 'headers' => array( 'SlideDeck-Version' => SLIDEDECK2_VERSION, 'User-Agent' => 'WordPress/' . get_bloginfo( "version" ), 'Referer' => get_bloginfo( "url" ), 'Verify' => '1' ), 'body' => null, 'cookies' => array( ), 'sslverify' => false ) );
  1700.  
  1701.         if( !is_wp_error( $response ) ) {
  1702.             $response_body = $response['body'];
  1703.             $response_json = json_decode( $response_body );
  1704.  
  1705.             // Only return if the response is a JSON response
  1706.             if( is_object( $response_json ) ) {
  1707.                 return $response_json;
  1708.             }
  1709.         }
  1710.  
  1711.         // Return boolean(false) if this request was not valid
  1712.         return false;
  1713.     }
  1714.  
  1715.     /**
  1716.      * Copy a lens
  1717.      *
  1718.      * Form submission response for copying a SlideDeck lens
  1719.      *
  1720.      * @uses SlideDeckLens::copy()
  1721.      */
  1722.     function copy_lens( ) {
  1723.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], "{$this->namespace}-copy-lens" ) ) {
  1724.             die( "false" );
  1725.         }
  1726.  
  1727.         $data = slidedeck2_sanitize( $_POST );
  1728.  
  1729.         if( !isset( $data['new_lens_slug'] ) ) {
  1730.             slidedeck2_set_flash( "<strong>ERROR:</strong> " . esc_html( __( "No lens slug was specified", $this->namespace ) ), true );
  1731.             wp_redirect( $_REQUEST['_wp_http_referer'] );
  1732.             exit ;
  1733.         }
  1734.  
  1735.         if( $this->Lens->get( $data['new_lens_slug'] ) !== false ) {
  1736.             slidedeck2_set_flash( "<strong>ERROR:</strong> " . esc_html( __( "The lens slug must be unique", $this->namespace ) ), true );
  1737.             wp_redirect( $_REQUEST['_wp_http_referer'] );
  1738.             exit ;
  1739.         }
  1740.  
  1741.         // A new suggested lens name from the user
  1742.         $new_lens_name = isset( $data['new_lens_name'] ) ? $data['new_lens_name'] : "";
  1743.         // A new suggested slug name from the user
  1744.         $new_lens_slug = isset( $data['new_lens_slug'] ) ? $data['new_lens_slug'] : "";
  1745.  
  1746.         $replace_js = false;
  1747.         if( $_REQUEST['create_or_copy'] == "create" )
  1748.             $replace_js = true;
  1749.  
  1750.         /**
  1751.          * If the lens is compatible with having its JS copied,
  1752.          * then we can attempt to do so. The eventual plan is to
  1753.          * have all lenses support this.
  1754.          */
  1755.         $lens_whitelist = array(
  1756.             'block-title',
  1757.             'fashion',
  1758.             'half-moon',
  1759.             'o-town',
  1760.             'proto',
  1761.             'tool-kit',
  1762.             'reporter',
  1763.             'video'
  1764.         );
  1765.         if( in_array( $data['lens'], $lens_whitelist ) )
  1766.             $replace_js = true;
  1767.  
  1768.         $lens = $this->Lens->copy( $data['lens'], $new_lens_name, $new_lens_slug, $replace_js );
  1769.  
  1770.         if( $lens ) {
  1771.             slidedeck2_set_flash( "<strong>" . esc_html( __( "Lens Copied Successfully", $this->namespace ) ) . "</strong>" );
  1772.             slidedeck2_km( "New Lens Copied/Created" );
  1773.         } else {
  1774.             slidedeck2_set_flash( __( "<strong>ERROR:</strong> Could not copy skin because the " . SLIDEDECK2_CUSTOM_LENS_DIR . " directory is not writable or does not exist.", 'slidedeck' ), true );
  1775.         }
  1776.  
  1777.         wp_redirect( $this->action( "/lenses" ) );
  1778.         exit ;
  1779.     }
  1780.  
  1781.     /**
  1782.      * Delete plugin update record meta to re-check plugin for version update
  1783.      *
  1784.      * @uses delete_option()
  1785.      * @uses wp_update_plugins()
  1786.      */
  1787.     public static function check_plugin_updates( ) {
  1788.         delete_site_transient( 'update_plugins' );
  1789.         wp_update_plugins( );
  1790.     }
  1791.  
  1792.     /**
  1793.      * Hook into register_deactivation_hook action
  1794.      *
  1795.      * Put code here that needs to happen when your plugin is deactivated
  1796.      *
  1797.      * @uses SlideDeckPlugin::check_plugin_updates()
  1798.      * @uses wp_remote_fopen()
  1799.      */
  1800.     static function deactivate( ) {
  1801.         SlideDeckLitePlugin::load_constants();
  1802.         self::check_plugin_updates( );
  1803.        
  1804.         include (dirname( __FILE__ ) . '/lib/template-functions.php');
  1805.  
  1806.         slidedeck2_km( "SlideDeck Deactivated" );
  1807.     }
  1808.    
  1809.     /**
  1810.      * Remove a lens (for system setups that require authorization)
  1811.      *
  1812.      * @since 2.8.0
  1813.      *
  1814.      * @param string $stylesheet Stylesheet of the theme to delete
  1815.      * @param string $redirect Redirect to page when complete.
  1816.      * @return mixed
  1817.      */
  1818.     function delete_lens_authorize( $lens, $redirect = '' ) {
  1819.         global $wp_filesystem;
  1820.    
  1821.         if( empty( $lens ) )
  1822.             return false;
  1823.        
  1824.         ob_start();
  1825.         if( empty( $redirect ) )
  1826.             $redirect = $this->action( '/lenses' ) . '&action=delete_authorize&lens=' . $lens . '&_wpnonce=' . wp_create_nonce( $this->namespace . '-delete-lens-authorize' );
  1827.         if( false === ( $credentials = request_filesystem_credentials( $redirect ) ) ) {
  1828.             $data = ob_get_contents();
  1829.             ob_end_clean();
  1830.             if( ! empty($data) ){
  1831.                 include_once( ABSPATH . 'wp-admin/admin-header.php');
  1832.                 echo $data;
  1833.                 include( ABSPATH . 'wp-admin/admin-footer.php');
  1834.                 exit;
  1835.             }
  1836.             return;
  1837.         }
  1838.    
  1839.         if( !WP_Filesystem( $credentials ) ) {
  1840.             request_filesystem_credentials( $url, '', true ); // Failed to connect, Error and request again
  1841.             $data = ob_get_contents();
  1842.             ob_end_clean();
  1843.             if ( ! empty($data) ) {
  1844.                 include_once( ABSPATH . 'wp-admin/admin-header.php');
  1845.                 echo $data;
  1846.                 include( ABSPATH . 'wp-admin/admin-footer.php');
  1847.                 exit;
  1848.             }
  1849.             return;
  1850.         }
  1851.    
  1852.         if( !is_object( $wp_filesystem ) )
  1853.             return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
  1854.    
  1855.         if( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() )
  1856.             return new WP_Error( 'fs_error', __( 'Filesystem error.' ), $wp_filesystem->errors );
  1857.    
  1858.         //Get the base plugin folder
  1859.         $custom_lenses_dir = SLIDEDECK2_CUSTOM_LENS_DIR;
  1860.         if( empty( $custom_lenses_dir ) )
  1861.             return new WP_Error( 'fs_no_themes_dir', __( 'Unable to locate SlideDeck 2 lens directory.', $this->namespace ) );
  1862.    
  1863.         $custom_lenses_dir = trailingslashit( $custom_lenses_dir );
  1864.         $custom_lenses_dir = trailingslashit( $custom_lenses_dir . $lens );
  1865.         $deleted = $wp_filesystem->delete( $custom_lenses_dir, true );
  1866.        
  1867.         if( !$deleted )
  1868.             return new WP_Error( 'could_not_remove_theme', sprintf( __('Could not fully remove the lens %s.', $this->namespace ), $lens ) );
  1869.        
  1870.         return true;
  1871.     }
  1872.  
  1873.     /**
  1874.      * Get dimensions of a SlideDeck
  1875.      *
  1876.      * Returns an array of the inner and outer dimensions of the SlideDeck
  1877.      *
  1878.      * @param array $slidedeck The SlideDeck object
  1879.      *
  1880.      * @return array
  1881.      */
  1882.     function get_dimensions( $slidedeck ) {
  1883.         $dimensions = array( );
  1884.  
  1885.         $sizes = apply_filters( "{$this->namespace}_sizes", $this->sizes, $slidedeck );
  1886.  
  1887.         $dimensions['width'] = $slidedeck['options']['size'] != "custom" ? $sizes[$slidedeck['options']['size']]['width'] : $slidedeck['options']['width'];
  1888.         $dimensions['height'] = $slidedeck['options']['size'] != "custom" ? $sizes[$slidedeck['options']['size']]['height'] : $slidedeck['options']['height'];
  1889.         $dimensions['outer_width'] = $dimensions['width'];
  1890.         $dimensions['outer_height'] = $dimensions['height'];
  1891.  
  1892.         do_action_ref_array( "{$this->namespace}_dimensions", array( &$dimensions['width'], &$dimensions['height'], &$dimensions['outer_width'], &$dimensions['outer_height'], &$slidedeck ) );
  1893.  
  1894.         return $dimensions;
  1895.     }
  1896.  
  1897.     /**
  1898.      * Get the URL for an iframe preview
  1899.      *
  1900.      * @param integer $id The ID of the SlideDeck to preview
  1901.      * @param integer $width Optional width of the SlideDeck itself
  1902.      * @param integer $height Optional height of the SlideDeck itself
  1903.      * @param integer $outer_width Optional outer width of the SlideDeck iframe
  1904.      * area
  1905.      * @param integer $outer_height Optional outer height of the SlideDeck iframe
  1906.      * area
  1907.      */
  1908.     function get_iframe_url( $id, $width = null, $height = null, $outer_width = null, $outer_height = null, $preview = false ) {
  1909.         $uniqueid = uniqid();
  1910.        
  1911.         if( func_num_args( ) < 5 ) {
  1912.             $slidedeck = $this->SlideDeck->get( $id );
  1913.             if( empty( $slidedeck ) )
  1914.                 return '';
  1915.  
  1916.             $slidedeck_dimensions = $this->get_dimensions( $slidedeck );
  1917.            
  1918.             if( !$preview ) $uniqueid = strtotime( $slidedeck['updated_at'] );
  1919.         }
  1920.  
  1921.         if( !isset( $width ) )
  1922.             $width = $slidedeck_dimensions['width'];
  1923.  
  1924.         if( !isset( $height ) )
  1925.             $height = $slidedeck_dimensions['height'];
  1926.  
  1927.         if( !isset( $outer_width ) )
  1928.             $outer_width = $slidedeck_dimensions['outer_width'];
  1929.  
  1930.         if( !isset( $outer_height ) )
  1931.             $outer_height = $slidedeck_dimensions['outer_height'];
  1932.  
  1933.         $dimensions = array( 'width' => $width, 'height' => $height, 'outer_width' => $outer_width, 'outer_height' => $outer_height );
  1934.        
  1935.         $url = admin_url( "admin-ajax.php?action={$this->namespace}_preview_iframe&uniqueid=" . $uniqueid . "&slidedeck={$id}&" . http_build_query( $dimensions ) );
  1936.        
  1937.         if( $preview ) $url .= "&preview=1";
  1938.        
  1939.         return $url;
  1940.     }
  1941.  
  1942.     /**
  1943.      * Insert SlideDeck iframe URL
  1944.      *
  1945.      * @global $post
  1946.      *
  1947.      * @return string
  1948.      */
  1949.     function get_insert_iframe_src( ) {
  1950.         global $post;
  1951.  
  1952.         $url = admin_url( "admin-ajax.php?action={$this->namespace}_insert_iframe&post_id={$post->ID}&TB_iframe=1&width=640&height=515" );
  1953.  
  1954.         return $url;
  1955.     }
  1956.  
  1957.     /**
  1958.      * Get Insert SlideDeck iframe table
  1959.      *
  1960.      * @param string $orderby What to order by
  1961.      * (post_date|post_title|slidedeck_source)
  1962.      * @param array $selected Optional array of pre-selected SlideDecks
  1963.      *
  1964.      * @uses SlideDeck::get()
  1965.      *
  1966.      * @return string
  1967.      */
  1968.     function get_insert_iframe_table( $orderby, $selected = array() ) {
  1969.         // Swap direction when ordering by date so newest is first
  1970.         $order = $orderby == "post_modified" ? 'DESC' : 'ASC';
  1971.         // Get all SlideDecks
  1972.         $slidedecks = $this->SlideDeck->get( null, $orderby, $order, 'publish' );
  1973.         // Namespace for use in the view
  1974.         $namespace = $this->namespace;
  1975.  
  1976.         ob_start( );
  1977.         include (SLIDEDECK2_DIRNAME . '/views/elements/_insert-iframe-table.php');
  1978.         $html = ob_get_contents( );
  1979.         ob_end_clean( );
  1980.  
  1981.         return $html;
  1982.     }
  1983.  
  1984.     /**
  1985.      * Get License Key
  1986.      *
  1987.      * Gets the current stored License Key
  1988.      *
  1989.      * @return string
  1990.      */
  1991.     function get_license_key( ) {
  1992.         // Is a license key defined as a constant?
  1993.         $defined_key = '';
  1994.         if( defined( 'SLIDEDECK_LICENSE_KEY' ) )
  1995.             $defined_key = SLIDEDECK_LICENSE_KEY;
  1996.        
  1997.         // Is there a stored key?
  1998.         $stored_key = $this->get_option( 'license_key' );
  1999.        
  2000.         // If the stored key is blank, then use the defined key.
  2001.         if( empty( $stored_key ) ){
  2002.             return (string) $defined_key;
  2003.         }
  2004.        
  2005.         return (string) $stored_key;
  2006.     }
  2007.  
  2008.     /**
  2009.      * Get available lenses for a SlideDeck
  2010.      *
  2011.      * Looks up all lenses and returns a filtered array of only those lenses
  2012.      * available to this SlideDeck. While the lens get() method is already
  2013.      * filtered, there are certain parameters that
  2014.      *
  2015.      * @param array $slidedeck The SlideDeck object
  2016.      *
  2017.      * @uses SlideDeckLens::get()
  2018.      *
  2019.      * @return array
  2020.      */
  2021.     function get_slidedeck_lenses( $slidedeck ) {
  2022.         $lenses = $this->Lens->get( );
  2023.  
  2024.         // Loop through sources to see if we have an all video SlideDeck
  2025.         $video_sources = array( 'youtube', 'vimeo', 'dailymotion' );
  2026.         $all_videos = true;
  2027.         foreach( $slidedeck['source'] as $source ) {
  2028.             if( !in_array( $source, $video_sources ) ) {
  2029.                 $all_videos = false;
  2030.             }
  2031.         }
  2032.  
  2033.         $filtered = array( );
  2034.         foreach( $lenses as $lens ) {
  2035.             // Skip the Twitter lens from use if Twitter is not the only source
  2036.             if( count( $slidedeck['source'] ) > 1 && in_array( "twitter", $slidedeck['source'] ) && $lens['slug'] == "twitter" ) {
  2037.                 continue;
  2038.             }
  2039.  
  2040.             if( $all_videos == false && $lens['slug'] == "video" ) {
  2041.                 continue;
  2042.             }
  2043.  
  2044.             $lens_intersect = array_intersect( $slidedeck['source'], $lens['meta']['sources'] );
  2045.             if( !empty( $lens_intersect ) ) {
  2046.                 $filtered[] = $lens;
  2047.             }
  2048.         }
  2049.         $lenses = $filtered;
  2050.  
  2051.         // Re-order things so that Tool-kit is always first
  2052.         $toolkit_index = -1;
  2053.         for( $i = 0; $i < count( $lenses ); $i++ ) {
  2054.             if( $lenses[$i]['slug'] == "tool-kit" ) {
  2055.                 $toolkit_index = $i;
  2056.             }
  2057.         }
  2058.  
  2059.         if( $toolkit_index != -1 ) {
  2060.             $toolkit = $lenses[$toolkit_index];
  2061.             array_splice( $lenses, $toolkit_index, 1 );
  2062.             array_unshift( $lenses, $toolkit );
  2063.         }
  2064.  
  2065.         return $lenses;
  2066.     }
  2067.  
  2068.     /**
  2069.      * Retrieve the stored plugin option or the default if no user specified
  2070.      * value is defined
  2071.      *
  2072.      * @param string $option_name The name of the option you wish to retrieve
  2073.      *
  2074.      * @uses get_option()
  2075.      *
  2076.      * @return mixed Returns the option value or false(boolean) if the option is
  2077.      * not found
  2078.      */
  2079.     function get_option( $option_name ) {
  2080.         // Load option values if they haven't been loaded already
  2081.         if( !isset( $this->options ) || empty( $this->options ) ) {
  2082.             $this->options = get_option( $this->option_name, $this->defaults );
  2083.         }
  2084.  
  2085.         if( array_key_exists( $option_name, $this->options ) ) {
  2086.             return $this->options[$option_name];
  2087.             // Return user's specified option value
  2088.         } elseif( array_key_exists( $option_name, $this->defaults ) ) {
  2089.             return $this->defaults[$option_name];
  2090.             // Return default option value
  2091.         }
  2092.         return false;
  2093.     }
  2094.  
  2095.     /**
  2096.      * Get the options model for this SlidDeck and lens
  2097.      *
  2098.      * @param array $slidedeck The SlideDeck object
  2099.      */
  2100.     function get_options_model( $slidedeck ) {
  2101.         $options_model = apply_filters( "{$this->namespace}_options_model", $this->SlideDeck->options_model, $slidedeck );
  2102.  
  2103.         return $options_model;
  2104.     }
  2105.    
  2106.     /**
  2107.      * Get the shortcode for a SlideDeck
  2108.      *
  2109.      * @param int $slidedeck_id The ID of the SlideDeck
  2110.      *
  2111.      * @return string
  2112.      */
  2113.     function get_slidedeck_shortcode( $slidedeck_id ) {
  2114.         $shortcode = "[SlideDeck2 id={$slidedeck_id}";
  2115.        
  2116.         if( $this->get_option( 'iframe_by_default' ) == true ) {
  2117.             $shortcode.= " iframe=1";
  2118.         }
  2119.        
  2120.         $shortcode.= "]";
  2121.        
  2122.         return $shortcode;
  2123.     }
  2124.  
  2125.     /**
  2126.      * Get all SlideDeck sources
  2127.      *
  2128.      * Returns an array of stock sources and adds a hook for loading additional
  2129.      * third-party sources
  2130.      *
  2131.      * @uses apply_filters()
  2132.      *
  2133.      * @return array
  2134.      */
  2135.     function get_sources( $source_slugs = array() ) {
  2136.         $sources = (array) apply_filters( "{$this->namespace}_get_sources", $this->sources );
  2137.  
  2138.         if( !empty( $source_slugs ) ) {
  2139.             if( !is_array( $source_slugs ) ) {
  2140.                 $source_slugs = array( $source_slugs );
  2141.             }
  2142.  
  2143.             $filtered_sources = array( );
  2144.             foreach( $sources as $source_name => $source_object ) {
  2145.                 if( in_array( $source_name, $source_slugs ) ) {
  2146.                     $filtered_sources[$source_name] = $source_object;
  2147.                 }
  2148.             }
  2149.             $sources = $filtered_sources;
  2150.         }
  2151.  
  2152.         uasort( $sources, array( &$this, '_sort_by_weight' ) );
  2153.  
  2154.         return $sources;
  2155.     }
  2156.  
  2157.     /**
  2158.      * Initialization function to hook into the WordPress init action
  2159.      *
  2160.      * Instantiates the class on a global variable and sets the class, actions
  2161.      * etc. up for use.
  2162.      */
  2163.     static function instance( ) {
  2164.         global $SlideDeckPlugin;
  2165.  
  2166.         // Only instantiate the Class if it hasn't been already
  2167.         if( !isset( $SlideDeckPlugin ) )
  2168.             $SlideDeckPlugin = new SlideDeckLitePlugin( );
  2169.     }
  2170.  
  2171.     /**
  2172.      * Convenience method to determine if we are viewing a SlideDeck plugin page
  2173.      *
  2174.      * @global $pagenow
  2175.      *
  2176.      * @return boolean
  2177.      */
  2178.     function is_plugin( ) {
  2179.         global $pagenow;
  2180.  
  2181.         if( !function_exists( 'get_current_screen' ) )
  2182.             return false;
  2183.  
  2184.         $screen_id = get_current_screen( );
  2185.         if( empty( $screen_id ) )
  2186.             return false;
  2187.  
  2188.         $is_plugin = (boolean) in_array(  get_current_screen( )->id, array_values( $this->menu ) );
  2189.  
  2190.         return $is_plugin;
  2191.     }
  2192.  
  2193.     /**
  2194.      * License Key Check
  2195.      *
  2196.      * Checks to see whether or not we need to hook into the admin
  2197.      * notices area and let the user know that they have not
  2198.      * entered their lciense key.
  2199.      *
  2200.      * @return boolean
  2201.      */
  2202.     function license_key_check( ) {
  2203.         global $current_user;
  2204.         wp_get_current_user( );
  2205.  
  2206.         $license_key = $this->get_license_key( );
  2207.         if( empty( $license_key ) && !isset( $_POST['submit'] ) ) {
  2208.             if( in_array( 'tier_10', SlideDeckLitePlugin::$addons_installed ) )
  2209.                 add_action( 'admin_notices', array( &$this, 'license_key_notice' ) );
  2210.            
  2211.             return false;
  2212.         } else {
  2213.             $license_key_status = $this->is_license_key_valid( $license_key );
  2214.             $addons_need_installing = false;
  2215.            
  2216.             if( isset( $license_key_status->addons ) ){
  2217.                 foreach( $license_key_status->addons as $addon_key => $addon_data ) {
  2218.                     if( !in_array( $addon_key, self::$addons_installed ) ) {
  2219.                         $addons_need_installing = true;
  2220.                     }
  2221.                 }
  2222.             }
  2223.            
  2224.             if( $addons_need_installing ) {
  2225.                 add_action( 'admin_notices', array( &$this, 'addons_available_message' ) );
  2226.             }
  2227.         }
  2228.        
  2229.         return true;
  2230.     }
  2231.  
  2232.     /**
  2233.      * Addons available for installation message
  2234.      *
  2235.      * Echoes the standard message to prompt a user to install available addons for their license
  2236.      * key that they have input.
  2237.      */
  2238.     function addons_available_message() {
  2239.         if( $this->is_plugin() || preg_match( "/^\/wp-admin\/plugins\.php/", $_SERVER['REQUEST_URI'] ) ) {
  2240.             $message = "<div id='{$this->namespace}-addon-notice' class='error updated fade'><p><strong>";
  2241.             $message .= sprintf( __( 'Addons are available for %s!', $this->namespace ), $this->friendly_name );
  2242.             $message .= "</strong> ";
  2243.             $message .= sprintf( __( 'There are addons available for your installation of %1$s. %2$sInstall Your Addons%3$s', $this->namespace ), $this->friendly_name, '<a class="button" style="text-decoration:none;color:#333;" href="' . $this->action( '/upgrades' ) . '">', '</a>' );
  2244.             $message .= "</p></div>";
  2245.    
  2246.             echo $message;
  2247.         }
  2248.     }
  2249.  
  2250.     /**
  2251.      * License Key Notice
  2252.      *
  2253.      * Echoes the standard message for a license key
  2254.      * that has not been entered.
  2255.      *
  2256.      */
  2257.     function license_key_notice( ) {
  2258.         $message = "<div id='{$this->namespace}-license-key-warning' class='error fade'><p><strong>";
  2259.         $message .= sprintf( __( '%s is not activated yet.', $this->namespace ), $this->friendly_name );
  2260.         $message .= "</strong> ";
  2261.         $message .= sprintf( __( 'You must %1$senter your license key%2$s to receive automatic updates and support.', $this->namespace ), '<a class="button" style="text-decoration:none;color:#333;" href="' . $this->action( '/options' ) . '">', '</a>' );
  2262.         $message .= "</p></div>";
  2263.  
  2264.         echo $message;
  2265.     }
  2266.  
  2267.     /**
  2268.      * Hook into load-$page action
  2269.      *
  2270.      * Implement help tabs for various admin pages related to SlideDeck
  2271.      */
  2272.     function load_admin_page( ) {
  2273.         $screen = get_current_screen( );
  2274.  
  2275.         if( !in_array( $screen->id, $this->menu ) ) {
  2276.             return false;
  2277.         }
  2278.  
  2279.         // Page action for sub-section handling
  2280.         $action = isset( $_GET['action'] ) ? $_GET['action'] : "";
  2281.  
  2282.         switch( $screen->id ) {
  2283.             // SlideDeck Manage Page
  2284.             case $this->menu['manage']:
  2285.                 switch( $action ) {
  2286.                     case "create":
  2287.                     case "edit":
  2288.                     break;
  2289.  
  2290.                     default:
  2291.                         /**
  2292.                          * TODO: Add FAQ and Help Tab elements
  2293.                          *
  2294.                          * $this->add_help_tab( 'whats-new', "What's New?" );
  2295.                          * $this->add_help_tab( 'faqs', "FAQs" );
  2296.                          */
  2297.                     break;
  2298.                 }
  2299.  
  2300.             break;
  2301.         }
  2302.  
  2303.         do_action( "{$this->namespace}_help_tabs", $screen, $action );
  2304.     }
  2305.  
  2306.     /**
  2307.      * Load Constants
  2308.      *
  2309.      * Conveninece function to load the constants files for
  2310.      * the activation and construct
  2311.      */
  2312.     static function load_constants() {
  2313.         if( defined( 'SLIDEDECK2_BASENAME' ) )
  2314.             return false;
  2315.        
  2316.         // SlideDeck Plugin Basename
  2317.         define( 'SLIDEDECK2_BASENAME', basename( __FILE__ ) );
  2318.         define( 'SLIDEDECK2_HOOK', preg_replace( "/\.php$/", "", SLIDEDECK2_BASENAME ) );
  2319.        
  2320.         // Include constants file
  2321.         require_once (dirname( __FILE__ ) . '/lib/constants.php');
  2322.     }
  2323.  
  2324.     /**
  2325.      * Hook into WordPress media_buttons action
  2326.      *
  2327.      * Adds Insert SlideDeck button next to Upload/Insert media button on post
  2328.      * and page editor pages
  2329.      */
  2330.     function media_buttons( ) {
  2331.         global $post;
  2332.  
  2333.         if( in_array( basename( $_SERVER['PHP_SELF'] ), array( 'post-new.php', 'page-new.php', 'post.php', 'page.php' ) ) ) {
  2334.             $img = '<img src="' . esc_url( SLIDEDECK2_URLPATH . '/images/icon-15x15.png?v=' . SLIDEDECK2_VERSION ) . '" width="15" height="15" />';
  2335.  
  2336.             echo '<a href="' . esc_url( $this->get_insert_iframe_src( ) ) . '" class="thickbox add_slidedeck" id="add_slidedeck" title="' . esc_attr__( 'Insert your SlideDeck', $this->namespace ) . '" onclick="return false;"> ' . $img . '</a>';
  2337.         }
  2338.     }
  2339.  
  2340.     /**
  2341.      * Create/Edit SlideDeck Page
  2342.      *
  2343.      * Expects either a "slidedeck" or "type" URL parameter to be present. If a
  2344.      * "slidedeck"
  2345.      * URL parameter is found, it will attempt to load the requested ID. If no
  2346.      * "slidedeck"
  2347.      * URL parameter is found and a "type" parameter is found, a new SLideDeck of
  2348.      * that type
  2349.      * will be created.
  2350.      *
  2351.      * @global $current_user
  2352.      *
  2353.      * @uses get_currentuserinfo()
  2354.      * @uses get_post_meta()
  2355.      * @uses get_user_meta()
  2356.      * @uses slidedeck2_set_flash()
  2357.      * @uses wp_redirect()
  2358.      * @uses SlideDeckPlugin::action()
  2359.      * @uses SlideDeck::get()
  2360.      * @uses SlideDeck::create()
  2361.      * @uses SlideDeckLens::get()
  2362.      * @uses apply_filters()
  2363.      */
  2364.     function page_create_edit( ) {
  2365.         global $current_user;
  2366.         get_currentuserinfo( );
  2367.  
  2368.         $form_action = "create";
  2369.         if( isset( $_REQUEST['slidedeck'] ) ) {
  2370.             $form_action = "edit";
  2371.         }
  2372.  
  2373.         $sources_available = $this->get_sources( );
  2374.  
  2375.         // Redirect to the manage page if creating and an invalid source was
  2376.         // specified
  2377.         if( $form_action == "create" ) {
  2378.             $source = $_REQUEST['source'];
  2379.             if( !is_array( $source ) )
  2380.                 $source = array( $source );
  2381.  
  2382.             $source_valid_message = "";
  2383.             if( !isset( $_REQUEST['source'] ) ) {
  2384.                 $source_valid_message = "You must specify a valid SlideDeck source";
  2385.             }
  2386.  
  2387.             $source_intersect = array_intersect( $source, array_keys( $sources_available ) );
  2388.             if( empty( $source_intersect ) ) {
  2389.                 $source_valid_message = "You do not have access to this SlideDeck source, please make sure you have the correct add-ons installed.";
  2390.             }
  2391.  
  2392.             if( !empty( $source_valid_message ) ) {
  2393.                 $this->post_header_redirect( $this->action( ), "<strong>ERROR:</strong> " . $source_valid_message );
  2394.             }
  2395.         }
  2396.  
  2397.         if( $form_action == "edit" ) {
  2398.             $slidedeck = $this->SlideDeck->get( $_REQUEST['slidedeck'] );
  2399.  
  2400.             $source_intersect = array_intersect( $slidedeck['source'], array_keys( $sources_available ) );
  2401.             if( empty( $source_intersect ) ) {
  2402.                 $this->post_header_redirect( $this->action( ), "<strong>ERROR:</strong> " . "You do not have access to this SlideDeck source, please make sure you have the correct add-ons installed." );
  2403.             }
  2404.  
  2405.             // SlideDeck's saved stage background
  2406.             $the_stage_background = get_post_meta( $slidedeck['id'], "{$this->namespace}_stage_background", true );
  2407.         } else {
  2408.             $slidedeck = $this->SlideDeck->create( "", $source );
  2409.  
  2410.             // Default stage background
  2411.             $the_stage_background = get_user_meta( $current_user->ID, "{$this->namespace}_default_stage_background", true );
  2412.         }
  2413.  
  2414.         // Set the default stage background if none has been set yet
  2415.         if( empty( $the_stage_background ) ) {
  2416.             $the_stage_background = "wood";
  2417.         }
  2418.  
  2419.         if( !$slidedeck ) {
  2420.             slidedeck2_set_flash( "Requested SlideDeck could not be loaded or created", true );
  2421.             wp_redirect( $this->action( ) );
  2422.             exit ;
  2423.         }
  2424.  
  2425.         $sizes = apply_filters( "{$this->namespace}_sizes", $this->sizes, $slidedeck );
  2426.         $lenses = $this->get_slidedeck_lenses( $slidedeck );
  2427.  
  2428.         // Set preview rendering dimensions to chosen size
  2429.         $dimensions = $this->get_dimensions( $slidedeck );
  2430.  
  2431.         // Iframe URL for preview
  2432.         $iframe_url = $this->get_iframe_url( $slidedeck['id'], $dimensions['width'], $dimensions['height'], $dimensions['outer_width'], $dimensions['outer_height'], true );
  2433.  
  2434.         $options_model = $this->get_options_model( $slidedeck );
  2435.  
  2436.         uksort( $options_model['Appearance']['titleFont']['values'], 'strnatcasecmp' );
  2437.         uksort( $options_model['Appearance']['bodyFont']['values'], 'strnatcasecmp' );
  2438.  
  2439.         // Trim out the Setup key
  2440.         $trimmed_options_model = $options_model;
  2441.         unset( $trimmed_options_model['Setup'] );
  2442.         $options_groups = $this->options_model_groups;
  2443.  
  2444.         $namespace = $this->namespace;
  2445.  
  2446.         // Get all available fonts
  2447.         $fonts = $this->SlideDeck->get_fonts( $slidedeck );
  2448.  
  2449.         // Backgrounds for the editor area
  2450.         $stage_backgrounds = $this->stage_backgrounds;
  2451.  
  2452.         $form_title = apply_filters( "{$namespace}_form_title", __( ucwords( $form_action ) . " SlideDeck", $this->namespace ), $slidedeck, $form_action );
  2453.        
  2454.         $has_saved_covers = false;
  2455.         if( class_exists( 'SlideDeckCovers' ) )
  2456.             $has_saved_covers = $this->Cover->has_saved_covers( $slidedeck['id'] );
  2457.  
  2458.         $slidedeck_is_dynamic = $this->slidedeck_is_dynamic( $slidedeck );
  2459.  
  2460.         include (SLIDEDECK2_DIRNAME . '/views/form.php');
  2461.     }
  2462.  
  2463.     /**
  2464.      * Manage Existing SlideDecks Page
  2465.      *
  2466.      * Loads all SlideDecks created by user and new creation options
  2467.      *
  2468.      * @uses SlideDeck::get()
  2469.      */
  2470.     function page_manage( ) {
  2471.         $order_options = $this->order_options;
  2472.         $orderby = get_option( "{$this->namespace}_manage_table_sort", reset( array_keys( $this->order_options ) ) );
  2473.         $order = $orderby == 'post_modified' ? 'DESC' : 'ASC';
  2474.  
  2475.         // Get a list of all SlideDecks in the system
  2476.         $slidedecks = $this->SlideDeck->get( null, $orderby, $order, 'publish' );
  2477.  
  2478.         // Available taxonomies for SlideDeck types
  2479.         $taxonomies = $this->taxonomies;
  2480.  
  2481.         // Get the available sources
  2482.         $sources = $this->get_sources( );
  2483.  
  2484.         // Initiate pointers on this page
  2485.         //$this->Pointers->pointer_lens_management();
  2486.  
  2487.         $default_view = get_user_option( "{$this->namespace}_default_manage_view" );
  2488.         if( !$default_view )
  2489.             $default_view = 'decks';
  2490.  
  2491.         $namespace = $this->namespace;
  2492.  
  2493.         $sidebar_ad_url = apply_filters( "{$this->namespace}_sidebar_ad_url", "//www.slidedeck.com/wordpress-plugin-iab/" );
  2494.  
  2495.         // Render the overview list
  2496.         include (SLIDEDECK2_DIRNAME . '/views/manage.php');
  2497.     }
  2498.  
  2499.     /**
  2500.      * The admin section options page rendering method
  2501.      *
  2502.      * @uses current_user_can()
  2503.      * @uses wp_die()
  2504.      */
  2505.     function page_options( ) {
  2506.         if( !current_user_can( 'manage_options' ) )
  2507.             wp_die( __( "You do not have privileges to access this page", $this->namespace ) );
  2508.  
  2509.         $defaults = array(
  2510.             'disable_wpautop' => false,
  2511.             'dont_enqueue_scrollwheel_library' => false,
  2512.             'dont_enqueue_easing_library' => false,
  2513.             'disable_edit_create' => false,
  2514.             'license_key' => "",
  2515.             'twitter_user' => "",
  2516.             'iframe_by_default' => false
  2517.         );
  2518.         $data = (array) get_option( $this->option_name, $defaults );
  2519.         $data = array_merge( $defaults, $data );
  2520.  
  2521.         $namespace = $this->namespace;
  2522.  
  2523.         /**
  2524.          * We handle these separately due to the funky characters.
  2525.          * Let's not risk breaking serialization.
  2526.          */
  2527.         // Get the Instagram Key
  2528.         $last_saved_instagram_access_token = get_option( $this->namespace . '_last_saved_instagram_access_token' );
  2529.        
  2530.         // Get the Google+ API  Key
  2531.         $last_saved_gplus_api_key = get_option( $this->namespace . '_last_saved_gplus_api_key' );
  2532.  
  2533.         include (SLIDEDECK2_DIRNAME . '/views/admin-options.php');
  2534.     }
  2535.  
  2536.     /**
  2537.      * The admin section upgrades page rendering method
  2538.      *
  2539.      * @uses current_user_can()
  2540.      * @uses wp_die()
  2541.      */
  2542.     function page_upgrades( ) {
  2543.         if( !current_user_can( 'manage_options' ) )
  2544.             wp_die( __( "You do not have privileges to access this page", $this->namespace ) );
  2545.  
  2546.         $namespace = $this->namespace;
  2547.         $plugins = array( );
  2548.         $license_key = slidedeck2_get_license_key( );
  2549.        
  2550.         /**
  2551.          * Here let's set the I'm back variable to true. This allows us to
  2552.          * know that they user is expecting a dialog showing the big install
  2553.          * button.
  2554.          * In this case, we don't need to immediately show the page, we can just
  2555.          * wait for a load.
  2556.          */
  2557.         if( isset( $_REQUEST['imback'] ) && $_REQUEST['imback'] === 'true' )
  2558.             $this->user_is_back = true;
  2559.  
  2560.         if( isset( $_GET['install'] ) && !empty( $_GET['install'] ) ) {
  2561.            
  2562.             // We're doing a SlideDeck addon install.
  2563.             SlideDeckLitePlugin::$slidedeck_addons_installing = true;
  2564.             include( 'lib/slidedeck-plugin-install.php' );
  2565.            
  2566.             if( isset( $_GET['package'] ) && !empty( $_GET['package'] ) ) {
  2567.                 foreach( (array) $_GET['package'] as $package ) {
  2568.                     /**
  2569.                      * Some servers don't allow http or https in a querystring.
  2570.                      * Understandable, but since we're logged in for this action, I think
  2571.                      * it's relatively safe. The woraround is to add the protocol here.
  2572.                      */
  2573.                     if( !preg_match( '/^http|https/', $package ) )
  2574.                         $package = 'http://' . $package;
  2575.                    
  2576.                     $plugins[] = $package;
  2577.                 }
  2578.             }
  2579.            
  2580.             $ssl = (isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on') ? 's' : '';
  2581.             $port = ($_SERVER['SERVER_PORT'] != '80') ? ':' . $_SERVER['SERVER_PORT'] : '';
  2582.             $url = sprintf( 'http%s://%s%s%s', $ssl, $_SERVER['SERVER_NAME'], $port, $_SERVER['REQUEST_URI'] );
  2583.  
  2584.             $type = '';
  2585.             $title = '';
  2586.             $nonce = '';
  2587.  
  2588.             $skin = new SlideDeckPluginInstallSkin( compact( 'type', 'title', 'nonce', 'url' ) );
  2589.             $skin->sd_header = isset( $data['body_header'] ) ? $data['body_header'] : '';
  2590.             $skin->sd_footer = isset( $data['body_footer'] ) ? $data['body_footer'] : '';
  2591.  
  2592.             $Installer = new SlideDeckPluginInstall( $skin );
  2593.  
  2594.             $Installer->install( $plugins );
  2595.  
  2596.             exit ;
  2597.         }
  2598.  
  2599.         include (SLIDEDECK2_DIRNAME . '/views/admin-upgrades.php');
  2600.     }
  2601.  
  2602.     /**
  2603.      * SlideDeck Lens Add New View
  2604.      *
  2605.      * Page to upload a new lens to the user's WordPress installation.
  2606.      *
  2607.      * @uses current_user_can()
  2608.      * @uses wp_die()
  2609.      */
  2610.     function page_lenses_add( ) {
  2611.         if( !current_user_can( 'install_themes' ) )
  2612.             wp_die( __( "You do not have privileges to access this page", $this->namespace ) );
  2613.  
  2614.         $namespace = $this->namespace;
  2615.  
  2616.         include (SLIDEDECK2_DIRNAME . '/views/lenses/add.php');
  2617.     }
  2618.    
  2619.     function page_lenses_delete_authorize() {
  2620.         if( !wp_verify_nonce( $_REQUEST['_wpnonce'], $this->namespace . '-delete-lens-authorize' ) ) {
  2621.             wp_die( __( "Sorry, you do not have permission to access this page", $this->namespace ) );
  2622.         }
  2623.        
  2624.         $redirect = "";
  2625.         if( isset( $_REQUEST['redirect'] ) ) {
  2626.             $redirect = $_REQUEST['redirect'];
  2627.         }
  2628.        
  2629.         if( isset( $_REQUEST['lens'] ) && !empty( $_REQUEST['lens'] ) ) {
  2630.             $this->delete_lens_authorize( $_REQUEST['lens'], $redirect );
  2631.            
  2632.             $this->post_header_redirect( $this->action( "/lenses" ), "<strong>Lens successfully deleted</strong>" );
  2633.             exit;
  2634.         }
  2635.     }
  2636.  
  2637.     /**
  2638.      * SlideDeck Lens Management Page
  2639.      *
  2640.      * Renders the primary lens management page where a user can see their
  2641.      * existing lenses, upload
  2642.      * new lenses, make copies of lenses, access a lens for editing and delete
  2643.      * existing lenses.
  2644.      *
  2645.      * @uses current_user_can()
  2646.      */
  2647.     function page_lenses_manage( ) {
  2648.         // Die if user cannot manage options
  2649.         if( !current_user_can( 'manage_options' ) )
  2650.             wp_die( __( "You do not have privileges to access this page", $this->namespace ) );
  2651.  
  2652.         $namespace = $this->namespace;
  2653.  
  2654.         $sources = $this->get_sources( );
  2655.  
  2656.         $lenses = $this->Lens->get( );
  2657.         foreach( $lenses as &$lens ) {
  2658.             $lens['is_protected'] = $this->Lens->is_protected( $lens['files']['meta'] );
  2659.         }
  2660.  
  2661.         $is_writable = $this->Lens->is_writable( );
  2662.  
  2663.         include (SLIDEDECK2_DIRNAME . '/views/lenses/manage.php');
  2664.     }
  2665.  
  2666.     /**
  2667.      * SlideDeck Lenses Page Router
  2668.      *
  2669.      * Routes admin page requests to the appropriate SlideDeck Lens page for
  2670.      * managing, editing
  2671.      * and uploading new lenses.
  2672.      */
  2673.     function page_lenses_route( ) {
  2674.         $action = array_key_exists( 'action', $_REQUEST ) ? $_REQUEST['action'] : "";
  2675.  
  2676.         // Define action as manage when accessing the manage page since the URL
  2677.         // does not contain an action query parameter
  2678.         if( empty( $action ) )
  2679.             $action = "manage";
  2680.  
  2681.         switch( $action ) {
  2682.             case "manage":
  2683.                 $this->page_lenses_manage( );
  2684.             break;
  2685.  
  2686.             case "add":
  2687.                 $this->page_lenses_add( );
  2688.             break;
  2689.            
  2690.             case "delete_authorize":
  2691.                 $this->page_lenses_delete_authorize();
  2692.             break;
  2693.  
  2694.             default:
  2695.                 do_action( "{$this->namespace}_page_lenses_route", $action );
  2696.             break;
  2697.         }
  2698.  
  2699.     }
  2700.  
  2701.     /**
  2702.      * SlideDecks Page Router
  2703.      *
  2704.      * Based off the action requested the page will either display the manage
  2705.      * view for managing
  2706.      * existing SlideDecks (default) or the editing/creation view for a
  2707.      * SlideDeck.
  2708.      *
  2709.      * @uses SlideDeckPlugin::page_manage()
  2710.      * @uses SlideDeckPlugin::page_create_edit()
  2711.      */
  2712.     function page_route( ) {
  2713.         $action = array_key_exists( 'action', $_REQUEST ) ? $_REQUEST['action'] : "";
  2714.  
  2715.         switch( $action ) {
  2716.             // Create a new SlideDeck
  2717.             case "create":
  2718.                 $this->page_create_edit( );
  2719.             break;
  2720.  
  2721.             // Edit existing SlideDecks
  2722.             case "edit":
  2723.                 $this->page_create_edit( );
  2724.             break;
  2725.  
  2726.             // Manage existing SlideDecks
  2727.             default:
  2728.                 $this->page_manage( );
  2729.             break;
  2730.         }
  2731.     }
  2732.  
  2733.     /**
  2734.      * Hook into plugin_action_links filter
  2735.      *
  2736.      * Adds a "Settings" link next to the "Deactivate" link in the plugin listing
  2737.      * page
  2738.      * when the plugin is active.
  2739.      *
  2740.      * @param object $links An array of the links to show, this will be the
  2741.      * modified variable
  2742.      * @param string $file The name of the file being processed in the filter
  2743.      */
  2744.     function plugin_action_links( $links, $file ) {
  2745.         $new_links = array( );
  2746.  
  2747.         if( $file == plugin_basename( SLIDEDECK2_DIRNAME . '/' . SLIDEDECK2_BASENAME ) ) {
  2748.             $new_links[] = '<a href="admin.php?page=' . SLIDEDECK2_BASENAME . '">' . __( 'Create New SlideDeck' ) . '</a>';
  2749.         }
  2750.  
  2751.         return array_merge( $new_links, $links );
  2752.     }
  2753.  
  2754.     /**
  2755.      * Post Header Redirect
  2756.      *
  2757.      * Outputs a JavaScript redirect directive to process redirects and set an
  2758.      * optional
  2759.      * message after headers have already been sent.
  2760.      *
  2761.      * @param string $location The destination
  2762.      * @param string $message Optional message to set
  2763.      */
  2764.     function post_header_redirect( $location, $message = "" ) {
  2765.         $url = admin_url( 'admin-ajax.php' ) . '?action=' . $this->namespace . '_post_header_redirect&_wpnonce=' . wp_create_nonce( "{$this->namespace}-post-header-redirect" );
  2766.         $url .= "&location=" . urlencode( $location );
  2767.         if( !empty( $message ) ) {
  2768.             $url .= "&message=" . urlencode( $message );
  2769.         }
  2770.  
  2771.         echo '<script type="text/javascript">document.location.href = "' . $url . '";</script>';
  2772.         exit ;
  2773.     }
  2774.  
  2775.     /**
  2776.      * Truncate the title string
  2777.      *
  2778.      * Truncate a title string for better visual display in Smart SlideDecks.This
  2779.      * function is multibyte aware so it should handle UTF-8 strings correctly.
  2780.      *
  2781.      * @param $text str The text to truncate
  2782.      * @param $length int (100) The length in characters to truncate to
  2783.      * @param $ending str The ending to tack onto the end of the truncated title
  2784.      * (if the title was truncated)
  2785.      */
  2786.     function prepare_title( $text, $length = 100, $ending = '&hellip;' ) {
  2787.         $truncated = mb_substr( strip_tags( $text ), 0, $length, 'UTF-8' );
  2788.  
  2789.         $original_length = function_exists( 'mb_strlen' ) ? mb_strlen( $text, 'UTF-8' ) : strlen( $text );
  2790.  
  2791.         if( $original_length > $length ) {
  2792.             $truncated .= $ending;
  2793.         }
  2794.  
  2795.         return $truncated;
  2796.     }
  2797.  
  2798.     /**
  2799.      * Used for printing out the JavaScript commands to load SlideDecks and
  2800.      * appropriately
  2801.      * read the DOM for positioning, sizing, dimensions, etc.
  2802.      *
  2803.      * @return Echo out the JavaScript tags generated by
  2804.      * slidedeck_process_template;
  2805.      */
  2806.     function print_footer_scripts( ) {
  2807.         echo $this->footer_scripts;
  2808.         echo '<style type="text/css" id="' . $this->namespace . '-footer-styles">' . $this->footer_styles . '</style>';
  2809.  
  2810.         do_action( "{$this->namespace}_print_footer_scripts" );
  2811.     }
  2812.  
  2813.     /**
  2814.      * Print JavaScript Constants
  2815.      *
  2816.      * prints some JavaScript constants that are used for
  2817.      * covers and other UI elements.
  2818.      */
  2819.     function print_javascript_constants( ) {
  2820.         echo '<script type="text/javascript">' . "\n";
  2821.         echo 'var slideDeck2URLPath = "' . SLIDEDECK2_URLPATH . '"' . "\n";
  2822.         echo 'var slideDeck2AddonsURL = "' . slidedeck2_action( "/upgrades" ) . '"' . "\n";
  2823.         echo 'var slideDeck2iframeByDefault = ' . var_export( $this->get_option( 'iframe_by_default' ), true ) . '; ' . "\n";
  2824.         echo '</script>' . "\n";
  2825.     }
  2826.  
  2827.     /**
  2828.      * Print JavaScript Constants
  2829.      *
  2830.      * prints some JavaScript constants that are used for
  2831.      * covers and other UI elements.
  2832.      */
  2833.     function print_header_javascript_constants( ) {
  2834.         echo '<script type="text/javascript">' . "\n";
  2835.         echo 'window.slideDeck2Version = "' . SLIDEDECK2_VERSION . '"' . "\n";
  2836.         echo 'window.slideDeck2Distribution = "' . strtolower( SLIDEDECK2_LICENSE ) . '"' . "\n";
  2837.         echo '</script>' . "\n";
  2838.     }
  2839.  
  2840.     /**
  2841.      * Run the the_content filters on the passed in text
  2842.      *
  2843.      * @param object $content The content to process
  2844.      * @param object $editing Process for editing or for viewing (viewing is
  2845.      * default)
  2846.      *
  2847.      * @uses do_shortcode()
  2848.      * @uses get_user_option()
  2849.      * @uses SlideDeckPlugin::get_option()
  2850.      * @uses wpautop()
  2851.      *
  2852.      * @return object $content The formatted content
  2853.      */
  2854.     function process_slide_content( $content, $editing = false ) {
  2855.         $content = stripslashes( $content );
  2856.  
  2857.         if( $editing === false ) {
  2858.             $content = do_shortcode( $content );
  2859.         }
  2860.  
  2861.         if( 'true' == get_user_option( 'rich_editing' ) || ($editing === false) ) {
  2862.             if( $this->get_option( 'disable_wpautop' ) != true ) {
  2863.                 $content = wpautop( $content );
  2864.             }
  2865.         }
  2866.  
  2867.         $content = str_replace( ']]>', ']]&gt;', $content );
  2868.  
  2869.         return $content;
  2870.     }
  2871.  
  2872.     /**
  2873.      * Add the SlideDeck button to the TinyMCE interface
  2874.      *
  2875.      * @param object $buttons An array of buttons for the TinyMCE interface
  2876.      *
  2877.      * @return object $buttons The modified array of TinyMCE buttons
  2878.      */
  2879.     function register_button( $buttons ) {
  2880.         array_push( $buttons, "separator", "slidedeck" );
  2881.         return $buttons;
  2882.     }
  2883.  
  2884.     /**
  2885.      * Register post types used by SlideDeck
  2886.      *
  2887.      * @uses register_post_type
  2888.      */
  2889.     function register_post_types( ) {
  2890.         register_post_type( 'slidedeck2', array( 'labels' => array( 'name' => 'slidedeck2', 'singular_name' => __( 'SlideDeck 2', $this->namespace ) ), 'public' => false ) );
  2891.     }
  2892.  
  2893.     /**
  2894.      * Route the user based off of environment conditions
  2895.      *
  2896.      * This function will handling routing of form submissions to the appropriate
  2897.      * form processor.
  2898.      *
  2899.      * @uses wp_verify_nonce()
  2900.      * @uses SlideDeckPlugin::admin_options_update()
  2901.      * @uses SlideDeckPlugin::save()
  2902.      * @uses SlideDeckPlugin::ajax_delete()
  2903.      */
  2904.     function route( ) {
  2905.         $uri = $_SERVER['REQUEST_URI'];
  2906.         $protocol = isset( $_SERVER['HTTPS'] ) ? 'https' : 'http';
  2907.         $hostname = $_SERVER['HTTP_HOST'];
  2908.         $url = "{$protocol}://{$hostname}{$uri}";
  2909.         $is_post = (bool)(strtoupper( $_SERVER['REQUEST_METHOD'] ) == "POST");
  2910.         $nonce = isset( $_REQUEST['_wpnonce'] ) ? $_REQUEST['_wpnonce'] : false;
  2911.  
  2912.         // Check if a nonce was passed in the request
  2913.         if( $nonce ) {
  2914.             // Handle POST requests
  2915.             if( $is_post ) {
  2916.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-update-options" ) ) {
  2917.                     $this->admin_options_update( );
  2918.                 }
  2919.  
  2920.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-create-slidedeck" ) || wp_verify_nonce( $nonce, "{$this->namespace}-edit-slidedeck" ) ) {
  2921.                     $this->save( );
  2922.                 }
  2923.  
  2924.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-delete-slidedeck" ) ) {
  2925.                     $this->ajax_delete( );
  2926.                 }
  2927.  
  2928.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-duplicate-slidedeck" ) ) {
  2929.                     $this->ajax_duplicate( );
  2930.                 }
  2931.  
  2932.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-save-lens" ) ) {
  2933.                     $this->save_lens( );
  2934.                 }
  2935.  
  2936.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-copy-lens" ) ) {
  2937.                     $this->copy_lens( );
  2938.                 }
  2939.  
  2940.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-delete-lens" ) ) {
  2941.                     $this->ajax_delete_lens( );
  2942.                 }
  2943.  
  2944.                 if( wp_verify_nonce( $nonce, "{$this->namespace}-cover-update" ) ) {
  2945.                     $this->update_cover( );
  2946.                 }
  2947.             }
  2948.             // Handle GET requests
  2949.             else {
  2950.  
  2951.             }
  2952.         }
  2953.  
  2954.         if( $this->is_plugin( ) && isset( $_GET['msg_deleted'] ) )
  2955.             slidedeck2_set_flash( __( "SlideDeck successfully deleted!", $this->namespace ) );
  2956.  
  2957.         if( preg_match( "/admin\.php\?.*page\=" . SLIDEDECK2_BASENAME . "\/feedback/", $uri ) ) {
  2958.             wp_redirect( "https://dtelepathy.zendesk.com/requests/new" );
  2959.             exit ;
  2960.         }
  2961.  
  2962.         do_action( "{$this->namespace}_route", $uri, $protocol, $hostname, $url, $is_post, $nonce );
  2963.     }
  2964.  
  2965.     /**
  2966.      * Save a SlideDeck
  2967.      */
  2968.     function save( ) {
  2969.         if( !isset( $_POST['id'] ) ) {
  2970.             return false;
  2971.         }
  2972.  
  2973.         $slidedeck_id = intval( $_POST['id'] );
  2974.  
  2975.         $slidedeck = $this->SlideDeck->save( $slidedeck_id, $_POST );
  2976.  
  2977.         $action = '&action=edit&slidedeck=' . $slidedeck_id;
  2978.  
  2979.         if( $_POST['action'] == "create" ) {
  2980.             $action .= '&firstsave=1';
  2981.             slidedeck2_km( "New SlideDeck Created", array( 'source' => $slidedeck['source'], 'lens' => $slidedeck['lens'] ) );
  2982.         }
  2983.  
  2984.         wp_redirect( $this->action( $action ) );
  2985.         exit ;
  2986.     }
  2987.  
  2988.     /**
  2989.      * Process saving of SlideDeck custom meta information for posts and pages
  2990.      *
  2991.      * @uses wp_verify_nonce()
  2992.      * @uses update_post_meta()
  2993.      * @uses delete_post_meta()
  2994.      */
  2995.     function save_post( ) {
  2996.         if( isset( $_POST['slidedeck-for-wordpress-dynamic-meta_wpnonce'] ) && !empty( $_POST['slidedeck-for-wordpress-dynamic-meta_wpnonce'] ) ) {
  2997.             if( !wp_verify_nonce( $_POST['slidedeck-for-wordpress-dynamic-meta_wpnonce'], 'slidedeck-for-wordpress' ) ) {
  2998.                 return false;
  2999.             }
  3000.  
  3001.             $slidedeck_post_meta = array( '_slidedeck_slide_title', '_slidedeck_post_featured' );
  3002.  
  3003.             foreach( $slidedeck_post_meta as $meta_key ) {
  3004.                 if( isset( $_POST[$meta_key] ) && !empty( $_POST[$meta_key] ) ) {
  3005.                     update_post_meta( $_POST['ID'], $meta_key, $_POST[$meta_key] );
  3006.                 } else {
  3007.                     delete_post_meta( $_POST['ID'], $meta_key );
  3008.                 }
  3009.             }
  3010.         }
  3011.     }
  3012.  
  3013.     /**
  3014.      * Lens Edit Form Submission
  3015.      *
  3016.      * @uses slidedeck2_sanitize()
  3017.      * @uses SlideDeckLens::save()
  3018.      */
  3019.     function save_lens( ) {
  3020.         $lens = $this->Lens->get( slidedeck2_sanitize( $_POST['lens'] ) );
  3021.         $lens_filename = dirname( $lens['files']['meta'] ) . "/" . slidedeck2_sanitize( $_POST['filename'] );
  3022.  
  3023.         if( $this->Lens->is_protected( $lens_filename ) )
  3024.             wp_die( '<h3>' . __( "Cannot Update Protected File", $this->namespace ) . '</h3><p>' . __( "The file you tried to write to is a protected file and cannot be overwritten.", $this->namespace ) . '</p><p><a href="' . $this->action( '/lenses' ) . '">' . __( "Return to Lens Manager", $this->namespace ) . '</a></p>' );
  3025.  
  3026.         // Lens CSS Content
  3027.         $lens_content = $_POST['lens_content'];
  3028.  
  3029.         $lens_meta = slidedeck2_sanitize( $_POST['data'] );
  3030.  
  3031.         // Save JSON meta if it was submitted
  3032.         if( !empty( $lens_meta ) ) {
  3033.             $lens_meta['contributors'] = array_map( 'trim', explode( ",", $lens_meta['contributors'] ) );
  3034.  
  3035.             $variations = array_map( 'trim', explode( ",", $lens_meta['variations'] ) );
  3036.             $lens_meta['variations'] = array( );
  3037.             foreach( $variations as $variation ) {
  3038.                 $lens_meta['variations'][strtolower( $variation )] = ucwords( $variation );
  3039.             }
  3040.  
  3041.             $this->Lens->save( $lens['files']['meta'], "", $lens['slug'], $lens_meta );
  3042.         }
  3043.  
  3044.         // Save the lens file
  3045.         $lens = $this->Lens->save( $lens_filename, $lens_content, $lens['slug'] );
  3046.  
  3047.         // Mark response as an error or not
  3048.         $error = (boolean)($lens === false);
  3049.  
  3050.         // Set response message default
  3051.         $message = "<strong>" . esc_html( __( "Update Successful!", $this->namespace ) ) . "</strong>";
  3052.         if( $error )
  3053.             $message = "<strong>ERROR:</strong> " . esc_html( __( "Could not write the lens.css file for this lens. Please check file write permissions.", $this->namespace ) );
  3054.  
  3055.         slidedeck2_set_flash( $message, $error );
  3056.  
  3057.         wp_redirect( $this->action( '/lenses&action=edit&slidedeck-lens=' . $lens['slug'] . "&filename=" . basename( $lens_filename ) ) );
  3058.         exit ;
  3059.     }
  3060.  
  3061.     /**
  3062.      * Sets up the user's cohort data
  3063.      *
  3064.      * @uses get_option()
  3065.      * @uses add_option()
  3066.      */
  3067.     static function set_cohort_data() {
  3068.         $data = array(
  3069.             'name' => self::$cohort_name,
  3070.             'variation' => self::$cohort_variation,
  3071.             'year' => date("Y"),
  3072.             'month' => date("m")
  3073.         );
  3074.        
  3075.         // Only set the cohort if it does not exist.
  3076.         if( get_option( self::$namespace . '_cohort', false ) === false ) {
  3077.             add_option( self::$namespace . '_cohort', $data );
  3078.         }
  3079.     }
  3080.    
  3081.     /**
  3082.      * Sets up the user's cohort data
  3083.      *
  3084.      * @uses get_option()
  3085.      * @uses add_option()
  3086.      */
  3087.     static function get_cohort_data() {
  3088.         return get_option( self::$namespace . '_cohort', false );
  3089.     }
  3090.  
  3091.     /**
  3092.      * Outputs the cohort info as a query string
  3093.      *
  3094.      * @param $starting_character
  3095.      *
  3096.      * @uses self::get_cohort_data()
  3097.      */
  3098.     static function get_cohort_query_string( $starting_character = '?' ) {
  3099.         $cohorts = self::get_cohort_data();
  3100.         $processed = array();
  3101.         foreach( $cohorts as $key => $value ){
  3102.             if( !empty( $value ) ){
  3103.                 $processed['cohort_' . $key] = $value;
  3104.             }
  3105.         }
  3106.         return $starting_character . http_build_query( $processed );
  3107.     }
  3108.  
  3109.     /**
  3110.      * Process the SlideDeck shortcode
  3111.      *
  3112.      * @param object $atts Attributes of the shortcode
  3113.      *
  3114.      * @uses shortcode_atts()
  3115.      * @uses slidedeck_process_template()
  3116.      *
  3117.      * @return object The processed shortcode
  3118.      */
  3119.     function shortcode( $atts ) {
  3120.         global $post;
  3121.         $default_deck_link_text = '';
  3122.        
  3123.         if( isset( $atts['id'] ) && !empty( $atts['id'] ) )
  3124.             $default_deck_link_text = get_the_title( $atts['id'] ) . ' <small>[' . __( "see the SlideDeck", $this->namespace ) . ']</small>';
  3125.        
  3126.         extract( shortcode_atts( array( 'id' => false, 'width' => null, 'height' => null, 'include_lens_files' => (boolean)true, 'iframe' => false, 'feed_link_text' => $default_deck_link_text, 'nocovers' => (boolean)false, 'preview' => (boolean)false ), $atts ) );
  3127.        
  3128.         if( $id !== false ) {
  3129.             // If this is a feed, just render a link
  3130.             if( $this->is_feed() )
  3131.                 return '<div class="slidedeck-link"><a href="' . get_permalink( $post->ID ) . '#SlideDeck-' . $id . '">' . $feed_link_text . '</a></div>';
  3132.        
  3133.             if( $iframe !== false ) {
  3134.                 return $this->_render_iframe( $id, $width, $height, $nocovers );
  3135.             } else {
  3136.                 return $this->SlideDeck->render( $id, array( 'width' => $width, 'height' => $height ), $include_lens_files, $preview );
  3137.             }
  3138.         } else {
  3139.             return "";
  3140.         }
  3141.     }
  3142.    
  3143.     /**
  3144.      * Is Feed?
  3145.      *
  3146.      * An extension of the is_feed() function.
  3147.      * We first check WWordPress' built in method and if it passes,
  3148.      * then we say yes this is a feed. If it fails, we try to detect FeedBurner
  3149.      *
  3150.      * @return boolean
  3151.      */
  3152.     function is_feed(){
  3153.         if( is_feed() ){
  3154.             return true;
  3155.         }elseif( preg_match( '/feedburner/', strtolower( $_SERVER['HTTP_USER_AGENT'] ) ) ){
  3156.             return true;
  3157.         }
  3158.         return false;
  3159.     }
  3160.    
  3161.     /**
  3162.      * SlideDeck After Get Filter
  3163.      *
  3164.      * @param array $slidedeck The SlideDeck object
  3165.      *
  3166.      * @return array
  3167.      */
  3168.     function slidedeck_after_get( $slidedeck ) {
  3169.         $slidedeck['options']['total_slides'] = min( $slidedeck['options']['total_slides'], SLIDEDECK_TOTAL_SLIDES_LITE );
  3170.         return $slidedeck;
  3171.     }
  3172.  
  3173.     /**
  3174.      * Hook into slidedeck_sidebar_ad_url filter
  3175.      */
  3176.     public function slidedeck_sidebar_ad_url( $url ) {
  3177.         $url = '//www.slidedeck.com/wordpress-plugin-iab-lite/';
  3178.        
  3179.         return $url;
  3180.     }
  3181.  
  3182.     /**
  3183.      * Hook into slidedeck_manage_sidebar_bottom action
  3184.      *
  3185.      * Output signup form in SlideDeck manage page sidebar.
  3186.      */
  3187.     public function slidedeck_manage_sidebar_bottom() {
  3188.         include (SLIDEDECK2_DIRNAME . '/views/elements/_sidebar-social.php' );
  3189.     }
  3190.  
  3191.     /**
  3192.      * Hook into slidedeck_create_custom_slidedeck_block filter
  3193.      *
  3194.      * Outputs the create custom slidedeck block on the manage page. By default,
  3195.      * the user
  3196.      * must have the Professional version of SlideDeck 2 installed to access
  3197.      * custom SlideDecks
  3198.      * so this will output a block with a link the upgrades page by default. The
  3199.      * Professional plugin will hook into this as well and output a block that
  3200.      * actually links
  3201.      * to the Custom SlideDeck type that it adds.
  3202.      *
  3203.      * @param string $html The HTML to be output
  3204.      *
  3205.      * @return string
  3206.      */
  3207.     function slidedeck_create_custom_slidedeck_block( $html ) {
  3208.         ob_start( );
  3209.         include (SLIDEDECK2_DIRNAME . '/views/elements/_create-custom-slidedeck-block.php');
  3210.         $html = ob_get_contents( );
  3211.         ob_end_clean( );
  3212.  
  3213.         return $html;
  3214.     }
  3215.    
  3216.     /**
  3217.      * Hook into slidedeck_create_dynamic_slidedeck_block filter
  3218.      *
  3219.      * Outputs the create dynamic slidedeck block on the manage page.
  3220.      *
  3221.      * @param string $html The HTML to be output
  3222.      *
  3223.      * @return string
  3224.      */
  3225.     function slidedeck_create_dynamic_slidedeck_block( $html ) {
  3226.         ob_start( );
  3227.         include (SLIDEDECK2_DIRNAME . '/views/elements/_create-dynamic-slidedeck-block.php');
  3228.         $html = ob_get_contents( );
  3229.         ob_end_clean( );
  3230.  
  3231.         return $html;
  3232.     }
  3233.  
  3234.     /**
  3235.      * Hook into slidedeck_content_control action
  3236.      *
  3237.      * Outputs the appropriate editor interface for either custom or dynamic
  3238.      * SlideDecks
  3239.      *
  3240.      * @param array $slidedeck The SlideDeck object
  3241.      *
  3242.      * @uses SlideDeck::is_dynamic()
  3243.      */
  3244.     function slidedeck_content_control( $slidedeck ) {
  3245.         if( $this->slidedeck_is_dynamic( $slidedeck ) ) {
  3246.             $namespace = $this->namespace;
  3247.  
  3248.             $sources = $this->get_sources( $slidedeck['source'] );
  3249.             if( isset( $sources['custom'] ) )
  3250.                 unset( $sources['custom'] );
  3251.  
  3252.             $slidedeck_id = $slidedeck['id'];
  3253.  
  3254.             include (SLIDEDECK2_DIRNAME . '/views/elements/_sources.php');
  3255.         }
  3256.     }
  3257.  
  3258.     function slidedeck_form_content_source( $slidedeck, $source ) {
  3259.         global $wp_scripts, $wp_styles;
  3260.  
  3261.         $loaded_sources = array_unique( $this->loadedSources );
  3262.  
  3263.         if( !is_array( $source ) ) {
  3264.             if( !in_array( $source, $loaded_sources ) ) {
  3265.                 if( isset( $wp_scripts->registered["slidedeck-deck-{$source}-admin"] ) ) {
  3266.                     $src = $wp_scripts->registered["slidedeck-deck-{$source}-admin"]->src;
  3267.                     echo '<script type="text/javascript" src="' . $src . (strpos( $src, "?" ) !== false ? "&" : "?") . "v=" . $wp_scripts->registered["slidedeck-deck-{$source}-admin"]->ver . '"></script>';
  3268.                 }
  3269.                 $href = $wp_styles->registered["slidedeck-deck-{$source}-admin"]->src;
  3270.                 echo '<link rel="stylesheet" type="text/css" href="' . $href . (strpos( $href, "?" ) !== false ? "&" : "?") . "v=" . $wp_styles->registered["slidedeck-deck-{$source}-admin"]->ver . '" />';
  3271.             }
  3272.         }
  3273.     }
  3274.  
  3275.     /**
  3276.      * Check if a SlideDeck is dynamic
  3277.      *
  3278.      * @param array $slidedeck The SlideDeck object
  3279.      *
  3280.      * @uses apply_filters()
  3281.      *
  3282.      * @return boolean
  3283.      */
  3284.     function slidedeck_is_dynamic( $slidedeck ) {
  3285.         $dynamic = (bool) apply_filters( "{$this->namespace}_is_dynamic", !in_array( "custom", $slidedeck['source'] ), $slidedeck );
  3286.  
  3287.         return $dynamic;
  3288.     }
  3289.    
  3290.     /**
  3291.      * After Lenses Hook.
  3292.      *
  3293.      * Outputs additional information about the lenses on the lens list view
  3294.      * on the SlideDeck options pane, when editing a deck.
  3295.      */
  3296.     function slidedeck_lens_selection_after_lenses( $slidedeck ) {
  3297.         include( SLIDEDECK2_DIRNAME . '/views/upsells/_upsell-additional-lenses.php' );
  3298.     }
  3299.    
  3300.     /**
  3301.      * Adds extra content to the base of the source modal
  3302.      */
  3303.     function slidedeck_source_modal_after_sources(){
  3304.         include( SLIDEDECK2_DIRNAME . '/views/upsells/_source-modal-additional-sources-upsell.php');
  3305.     }
  3306.  
  3307.     /**
  3308.      * Sort all options by weight
  3309.      *
  3310.      * @param array $options_model The Options Model Array
  3311.      * @param array $slidedeck The SlideDeck object
  3312.      *
  3313.      * @return array
  3314.      */
  3315.     function slidedeck_options_model( $options_model, $slidedeck ) {
  3316.         // Sorted options model to return
  3317.         $sorted_options_model = array( );
  3318.  
  3319.         foreach( $options_model as $options_group => $options ) {
  3320.             $sorted_options_model[$options_group] = array( );
  3321.  
  3322.             $sorted_options_group = $options;
  3323.             uasort( $sorted_options_group, array( &$this, '_sort_by_weight' ) );
  3324.  
  3325.             $sorted_options_model[$options_group] = $sorted_options_group;
  3326.         }
  3327.  
  3328.         return $sorted_options_model;
  3329.     }
  3330.  
  3331.     /**
  3332.      * Slide Count
  3333.      *
  3334.      * @param array $options_model The Options Model Array
  3335.      * @param array $slidedeck The SlideDeck object
  3336.      *
  3337.      * @return array
  3338.      */
  3339.     function slidedeck_options_model_slide_count( $options_model, $slidedeck ) {
  3340.         $options_model['Setup']['total_slides']['interface']['max'] = SLIDEDECK_TOTAL_SLIDES_LITE;
  3341.         $options_model['Setup']['total_slides']['interface']['min'] = 1;
  3342.         return $options_model;
  3343.     }
  3344.  
  3345.     /**
  3346.      * Save SlideDeck Cover data
  3347.      *
  3348.      * @uses slidedeck2_sanitize()
  3349.      * @uses SlideDeckCovers::save()
  3350.      */
  3351.     function update_cover( ) {
  3352.         $data = slidedeck2_sanitize( $_REQUEST );
  3353.  
  3354.         $this->Cover->save( $data['slidedeck'], $data );
  3355.  
  3356.         die( "Saved!" );
  3357.     }
  3358.  
  3359.     /**
  3360.      * Upload lens request submission
  3361.      *
  3362.      * Adaptation of WordPress core theme upload and install routines for
  3363.      * uploading and
  3364.      * installing lenses via a ZIP file upload.
  3365.      *
  3366.      * @uses wp_verify_nonce()
  3367.      * @uses wp_die()
  3368.      * @uses wp_enqueue_style()
  3369.      * @uses add_query_tag()
  3370.      * @uses slidedeck2_action()
  3371.      * @uses SlideDeckLens::copy_inc()
  3372.      * @uses File_Upload_Upgrader
  3373.      * @uses SlideDeck_Lens_Installer_Skin
  3374.      * @uses SlideDeck_Lens_Upload
  3375.      * @uses SlideDeck_Lens_Upload::install()
  3376.      * @uses is_wp_error()
  3377.      * @uses File_Upload_Upgrader::cleanup()
  3378.      */
  3379.     function upload_lens( ) {
  3380.         if( !current_user_can( 'install_themes' ) )
  3381.             wp_die( __( 'You do not have sufficient permissions to install SlideDeck lenses on this site.', $this->namespace ) );
  3382.  
  3383.         check_admin_referer( "{$this->namespace}-upload-lens" );
  3384.  
  3385.         // Load the SlideDeck Lens Upload Classes
  3386.         if( !class_exists( 'SlideDeckLensUpload' ) )
  3387.             include (SLIDEDECK2_DIRNAME . '/classes/slidedeck-lens-upload.php');
  3388.  
  3389.         $file_upload = new File_Upload_Upgrader( 'slidedecklenszip', 'package' );
  3390.  
  3391.         $title = __( "Upload SlideDeck Lens", $this->namespace );
  3392.         $parent_file = "";
  3393.         $submenu_file = "";
  3394.         wp_enqueue_style( "{$this->namespace}-admin" );
  3395.         wp_enqueue_style( "{$this->namespace}-admin-lite" );
  3396.         require_once (ABSPATH . 'wp-admin/admin-header.php');
  3397.  
  3398.         $title = sprintf( __( "Installing SlideDeck Lens from uploaded file: %s", 'slidedeck' ), basename( $file_upload->filename ) );
  3399.         $nonce = "{$this->namespace}-upload-lens";
  3400.         $url = add_query_arg( array( 'package' => $file_upload->id ), 'update.php?action=upload-slidedeck-lens' );
  3401.         $type = 'upload';
  3402.        
  3403.         $lens_dirname = preg_replace( "/\.([a-zA-Z0-9]+)$/", "", basename( $file_upload->filename ) );
  3404.  
  3405.         $upgrader = new SlideDeck_Lens_Upload( new SlideDeck_Lens_Installer_Skin( compact( 'type', 'title', 'lens_dirname', 'nonce', 'url' ) ) );
  3406.         $result = $upgrader->install( $file_upload->package );
  3407.  
  3408.         if( $result || is_wp_error( $result ) )
  3409.             $file_upload->cleanup( );
  3410.  
  3411.         include (ABSPATH . 'wp-admin/admin-footer.php');
  3412.     }
  3413.  
  3414.     /**
  3415.      * Hook into wp_fullscreen_buttons filter
  3416.      *
  3417.      * Adds insert SlideDeck button to fullscreen TinyMCE editor
  3418.      *
  3419.      * @param array $buttons Array of buttons to render
  3420.      *
  3421.      * @return array
  3422.      */
  3423.     function wp_fullscreen_buttons( $buttons ) {
  3424.         $buttons[] = 'separator';
  3425.  
  3426.         $buttons['slidedeck'] = array( 'title' => __( "Insert SlideDeck", $this->namespace ), 'onclick' => "tinyMCE.execCommand('mceSlideDeck2');", 'both' => false );
  3427.  
  3428.         return $buttons;
  3429.     }
  3430.  
  3431.     /**
  3432.      * Determine which SlideDecks are being loaded on this page
  3433.      *
  3434.      * @uses SlideDeck::get()
  3435.      */
  3436.     function wp_hook( ) {
  3437.         global $posts;
  3438.  
  3439.         if( isset( $posts ) && !empty( $posts ) ) {
  3440.             $slidedeck_ids = array( );
  3441.  
  3442.             // Process through $posts for the existence of SlideDecks
  3443.             foreach( (array) $posts as $post ) {
  3444.                 $matches = array( );
  3445.                 preg_match_all( '/\[SlideDeck2( ([a-zA-Z0-9]+)\=\'?([a-zA-Z0-9\%\-_\.]+)\'?)*\]/', $post->post_content, $matches );
  3446.                 if( !empty( $matches[0] ) ) {
  3447.                     foreach( $matches[0] as $match ) {
  3448.                         $str = $match;
  3449.                         $str_pieces = explode( " ", $str );
  3450.                         foreach( $str_pieces as $piece ) {
  3451.                             $attrs = explode( "=", $piece );
  3452.                             if( $attrs[0] == "id" ) {
  3453.                                 // Add the ID of this SlideDeck to the ID array
  3454.                                 // for loading
  3455.                                 $slidedeck_ids[] = intval( str_replace( "'", '', $attrs[1] ) );
  3456.                             }
  3457.                         }
  3458.                     }
  3459.                 }
  3460.             }
  3461.  
  3462.             if( !empty( $slidedeck_ids ) ) {
  3463.                 // Load SlideDecks used on this URL passing the array of IDs
  3464.                 $slidedecks = $this->SlideDeck->get( $slidedeck_ids );
  3465.  
  3466.                 // Loop through SlideDecks used on this page and add their lenses
  3467.                 // to the $lenses_included array for later use
  3468.                 foreach( (array) $slidedecks as $slidedeck ) {
  3469.                     $lens_slug = isset( $slidedeck['lens'] ) && !empty( $slidedeck['lens'] ) ? $slidedeck['lens'] : 'default';
  3470.  
  3471.                     $this->lenses_included[$lens_slug] = true;
  3472.                     foreach( $slidedeck['source'] as $source ) {
  3473.                         $this->sources_included[$source] = true;
  3474.                     }
  3475.  
  3476.                     /**
  3477.                      * @deprecated DEPRECATED third $type_slug parameter since
  3478.                      * 2.1
  3479.                      */
  3480.                     do_action( "{$this->namespace}_pre_load", $slidedeck, $lens_slug, "", $slidedeck['source'] );
  3481.                 }
  3482.             }
  3483.         }
  3484.     }
  3485.  
  3486.     /**
  3487.      * Load the SlideDeck library JavaScript and support files in the public
  3488.      * views to render SlideDecks
  3489.      *
  3490.      * @uses wp_register_script()
  3491.      * @uses wp_enqueue_script()
  3492.      * @uses SlideDeck::get()
  3493.      * @uses SlideDeckPlugin::is_plugin()
  3494.      * @uses SlideDeckLens::get()
  3495.      */
  3496.     function wp_print_scripts( ) {
  3497.         wp_enqueue_script( 'jquery' );
  3498.  
  3499.         if( $this->get_option( 'dont_enqueue_scrollwheel_library' ) != true ) {
  3500.             wp_enqueue_script( 'scrolling-js' );
  3501.         }
  3502.  
  3503.         if( $this->get_option( 'dont_enqueue_easing_library' ) != true ) {
  3504.             wp_enqueue_script( 'jquery-easing' );
  3505.         }
  3506.  
  3507.         if( !is_admin( ) ) {
  3508.             wp_enqueue_script( "{$this->namespace}-library-js" );
  3509.             wp_enqueue_script( "{$this->namespace}-public" );
  3510.             wp_enqueue_script( "twitter-intent-api" );
  3511.         }
  3512.  
  3513.         // Make accommodations for the editing view to only load the lens files
  3514.         // for the SlideDeck being edited
  3515.         if( $this->is_plugin( ) ) {
  3516.             if( isset( $_GET['slidedeck'] ) ) {
  3517.                 $slidedeck = $this->SlideDeck->get( $_GET['slidedeck'] );
  3518.                 $lens = $slidedeck['lens'];
  3519.                 $this->lenses_included = array( $lens => 1 );
  3520.             }
  3521.         }
  3522.  
  3523.         foreach( (array) $this->lenses_included as $lens_slug => $val ) {
  3524.             $lens = $this->Lens->get( $lens_slug );
  3525.             if( isset( $lens['script_url'] ) ) {
  3526.                 wp_register_script( "{$this->namespace}-lens-js-{$lens_slug}", $lens['script_url'], array( 'jquery', "{$this->namespace}-library-js" ), SLIDEDECK2_VERSION );
  3527.                 wp_enqueue_script( "{$this->namespace}-lens-js-{$lens_slug}" );
  3528.                 if( $this->is_plugin( ) ) {
  3529.                     if( isset( $lens['admin_script_url'] ) ) {
  3530.                         wp_register_script( "{$this->namespace}-lens-admin-js-{$lens_slug}", $lens['admin_script_url'], array( 'jquery', "{$this->namespace}-admin" ), SLIDEDECK2_VERSION, true );
  3531.                         wp_enqueue_script( "{$this->namespace}-lens-admin-js-{$lens_slug}" );
  3532.                     }
  3533.                 }
  3534.             }
  3535.         }
  3536.  
  3537.         $this->lenses_loaded = true;
  3538.     }
  3539.  
  3540.     /**
  3541.      * Load SlideDeck support CSS files for lenses used by SlideDecks on a page
  3542.      *
  3543.      * @uses SlideDeckLens::get()
  3544.      * @uses SlideDeckLens::get_css()
  3545.      */
  3546.     function wp_print_styles( ) {
  3547.         foreach( (array) $this->lenses_included as $lens_slug => $val ) {
  3548.             $lens = $this->Lens->get( $lens_slug );
  3549.             echo $this->Lens->get_css( $lens );
  3550.         }
  3551.  
  3552.         wp_enqueue_style( $this->namespace );
  3553.     }
  3554.  
  3555.     /**
  3556.      * Register scripts used by this plugin for enqueuing elsewhere
  3557.      *
  3558.      * @uses wp_register_script()
  3559.      */
  3560.     function wp_register_scripts( ) {
  3561.         // Admin JavaScript
  3562.         wp_register_script( "{$this->namespace}-admin", SLIDEDECK2_URLPATH . "/js/{$this->namespace}-admin" . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . ".js", array( 'jquery', 'media-upload', 'fancy-form', 'simplemodal' ), SLIDEDECK2_VERSION, true );
  3563.         // Lite Admin JavaScript
  3564.         wp_register_script( "{$this->namespace}-admin-lite", SLIDEDECK2_URLPATH . "/js/{$this->namespace}-admin-lite" . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . ".js", array( 'slidedeck-admin' ), SLIDEDECK2_VERSION, true );
  3565.         // SlideDeck JavaScript Core
  3566.         wp_register_script( "{$this->namespace}-library-js", SLIDEDECK2_URLPATH . '/js/slidedeck.jquery' . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . '.js', array( 'jquery' ), '1.3.9' );
  3567.         // Public Javascript
  3568.         wp_register_script( "{$this->namespace}-public", SLIDEDECK2_URLPATH . '/js/slidedeck-public' . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . '.js', array( 'jquery', 'slidedeck-library-js' ), SLIDEDECK2_VERSION );
  3569.         // Mouse Scrollwheel jQuery event library
  3570.         wp_register_script( "scrolling-js", SLIDEDECK2_URLPATH . '/js/jquery-mousewheel/jquery.mousewheel.min.js', array( 'jquery' ), '3.0.6' );
  3571.         // Fancy Form Elements jQuery library
  3572.         wp_register_script( "fancy-form", SLIDEDECK2_URLPATH . '/js/fancy-form' . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . '.js', array( 'jquery' ), '1.0.0' );
  3573.         // Tooltipper jQuery library
  3574.         wp_register_script( "tooltipper", SLIDEDECK2_URLPATH . '/js/tooltipper' . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . '.js', array( 'jquery' ), '1.0.1' );
  3575.         // jQuery Easing Library
  3576.         wp_register_script( "jquery-easing", SLIDEDECK2_URLPATH . '/js/jquery.easing.1.3.js', array( 'jquery' ), '1.3' );
  3577.         // jQuery MiniColors Color Picker
  3578.         wp_register_script( "jquery-minicolors", SLIDEDECK2_URLPATH . '/js/jquery-minicolors/jquery.minicolors.min.js', array( 'jquery' ), '7d21e3c363' );
  3579.         // SlideDeck Preview Updater
  3580.         wp_register_script( "{$this->namespace}-preview", SLIDEDECK2_URLPATH . '/js/slidedeck-preview' . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . '.js', array( 'jquery' ), SLIDEDECK2_VERSION );
  3581.         // Simple Modal Library
  3582.         wp_register_script( "simplemodal", SLIDEDECK2_URLPATH . '/js/simplemodal' . (SLIDEDECK2_ENVIRONMENT == 'development' ? '.dev' : '') . '.js', array( 'jquery' ), '1.0.1' );
  3583.         // Zero Clipboard
  3584.         wp_register_script( "zeroclipboard", SLIDEDECK2_URLPATH . '/js/zeroclipboard/ZeroClipboard.js', array( 'jquery' ), '1.0.7' );
  3585.         // Twitter Intent API
  3586.         wp_register_script( "twitter-intent-api", (is_ssl( ) ? 'https:' : 'http:') . "//platform.twitter.com/widgets.js", array( ), '1316526300' );
  3587.         // Froogaloop for handling Vimeo videos
  3588.         wp_register_script( 'froogaloop', SLIDEDECK2_URLPATH . '/js/froogaloop.min.js', array( ), SLIDEDECK2_VERSION, true );
  3589.         // Youtube JavaScript API
  3590.         wp_register_script( 'youtube-api', (is_ssl( ) ? 'https' : 'http') . '://www.youtube.com/player_api', array( ), SLIDEDECK2_VERSION, true );
  3591.         // Dailymotion JavaScript API
  3592.         wp_register_script( 'dailymotion-api', (is_ssl( ) ? 'https' : 'http') . '://api.dmcdn.net/all.js', array( ), SLIDEDECK2_VERSION, true );
  3593.         // jQuery Masonry
  3594.         wp_register_script( 'jquery-masonry', SLIDEDECK2_URLPATH . '/js/jquery.masonry.js', array( 'jquery' ), '2.1.01' );
  3595.     }
  3596.  
  3597.     /**
  3598.      * Register styles used by this plugin for enqueuing elsewhere
  3599.      *
  3600.      * @uses wp_register_style()
  3601.      */
  3602.     function wp_register_styles( ) {
  3603.         // Admin Stylesheet
  3604.         wp_register_style( "{$this->namespace}-admin", SLIDEDECK2_URLPATH . "/css/{$this->namespace}-admin.css", array( ), SLIDEDECK2_VERSION, 'screen' );
  3605.         // Admin Stylesheet
  3606.         wp_register_style( "{$this->namespace}-admin-lite", SLIDEDECK2_URLPATH . "/css/{$this->namespace}-admin-lite.css", array( ), SLIDEDECK2_VERSION, 'screen' );
  3607.         // Gplus How-to Modal Stylesheet
  3608.         wp_register_style( "gplus-how-to-modal", SLIDEDECK2_URLPATH . "/css/gplus-how-to-modal.css", array( ), SLIDEDECK2_VERSION, 'screen' );
  3609.         // Public Stylesheet
  3610.         wp_register_style( $this->namespace, SLIDEDECK2_URLPATH . "/css/slidedeck.css", array( ), SLIDEDECK2_VERSION, 'screen' );
  3611.         // Fancy Form Elements library
  3612.         wp_register_style( "fancy-form", SLIDEDECK2_URLPATH . '/css/fancy-form.css', array( ), '1.0.0', 'screen' );
  3613.         // jQuery MiniColors Color Picker
  3614.         wp_register_style( "jquery-minicolors", SLIDEDECK2_URLPATH . '/css/jquery.minicolors.css', array( ), '7d21e3c363', 'screen' );
  3615.     }
  3616.  
  3617. }
  3618.  
  3619. register_activation_hook( __FILE__, array( 'SlideDeckLitePlugin', 'activate' ) );
  3620. register_deactivation_hook( __FILE__, array( 'SlideDeckLitePlugin', 'deactivate' ) );
  3621.  
  3622. // SlideDeck Personal should load, then Lite, then Professional, then Developer
  3623. add_action( 'plugins_loaded', array( 'SlideDeckLitePlugin', 'instance' ), 15 );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement