PluginProbe ʕ •ᴥ•ʔ
Slider, Gallery, and Carousel by MetaSlider – Image Slider, Video Slider / 3.10.1
Slider, Gallery, and Carousel by MetaSlider – Image Slider, Video Slider v3.10.1
3.109.0 3.27.10 3.27.11 3.27.12 3.27.13 3.27.14 3.27.2 3.27.3 3.27.4 3.27.5 3.27.6 3.27.7 3.27.8 3.27.9 3.27.9-beta.2 3.27.9-beta.3 3.28.0 3.28.1 3.28.2 3.28.3 3.29.0 3.29.1 3.3.1 3.3.2 3.3.3 3.3.4 3.3.4.1 3.3.5 3.3.6 3.3.7 3.30.0 3.30.1 3.31.0 3.32.0 3.33.0 3.34.0 3.35.0 3.36.0 3.37.0 3.4 3.4.1 3.4.2 3.4.3 3.40.0 3.5 3.5.1 3.50.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.5 3.6.6 3.6.7 3.6.8 3.60.0 3.60.1 3.61.0 3.62.0 3.7.0 3.7.1 3.7.2 3.70.0 3.70.1 3.70.2 3.8.0 3.8.1 3.80.0 3.9.0 3.9.1 3.90.0 3.90.1 3.91.0 3.92.0 3.92.1 3.93.0 3.94.0 3.95.0 3.96.0 3.97.0 3.98.0 3.99.0 3.107.0 3.108.0 3.11.0 3.11.1 3.12.1 3.13.0 3.13.1 3.14.0 3.15.0 3.15.1 3.15.2 3.15.3 3.16.0 3.16.1 3.16.2 3.16.4 3.17.0 3.17.1 3.17.2 3.17.3 3.17.4 3.17.5 3.17.6 3.18.0 3.18.1 3.18.2 3.18.3 3.18.4 3.18.5 3.18.6 3.18.7 3.18.8 3.18.9 3.19.0 3.19.1 3.2.1 3.20.0 3.20.1 3.20.2 3.20.3 3.21.0 3.22.0 3.22.1 3.23.0 3.23.1 3.23.2 3.23.3 3.23.4 3.23.5 3.24.0 3.25.0 3.25.1 3.25.2 3.26.0 3.27.0 3.27.1 trunk 1.0 1.0.1 1.1 1.2.1 1.3 2.0.2 2.1.6 2.2.2 2.3 2.4.2 2.5.1 2.6.3 2.7.2 2.8.1 2.9.1 3.0.1 3.1.1 3.10.0 3.10.1 3.10.2 3.10.3 3.100.0 3.100.1 3.101.0 3.102.0 3.103.0 3.104.0 3.105.0 3.106.0
ml-slider / ml-slider.php
ml-slider Last commit date
admin 7 years ago assets 7 years ago inc 7 years ago languages 7 years ago themes 7 years ago ml-slider.php 7 years ago readme.txt 7 years ago
ml-slider.php
2218 lines
1 <?php
2 // @codingStandardsIgnoreLine
3 /*
4 * MetaSlider. Slideshow plugin for WordPress.
5 *
6 * Plugin Name: MetaSlider
7 * Plugin URI: https://www.metaslider.com
8 * Description: Easy to use slideshow plugin. Create SEO optimised responsive slideshows with Nivo Slider, Flex Slider, Coin Slider and Responsive Slides.
9 * Version: 3.10.1
10 * Author: Team Updraft
11 * Author URI: https://www.metaslider.com
12 * License: GPL-2.0+
13 * Copyright: 2017- Simba Hosting Ltd
14 *
15 * Text Domain: ml-slider
16 * Domain Path: /languages
17 */
18
19 if (!defined('ABSPATH')) die('No direct access.');
20
21 if (!class_exists('MetaSliderPlugin')) :
22
23 /**
24 * Register the plugin.
25 *
26 * Display the administration panel, insert JavaScript etc.
27 */
28 class MetaSliderPlugin {
29
30 /**
31 * Meta slider version number
32 *
33 * @var string
34 */
35 public $version = '3.10.1';
36
37 /**
38 * Specific SLider
39 *
40 * @var MetaSlider
41 */
42 public $slider = null;
43
44 /**
45 * Instance object
46 *
47 * @var object
48 * @see get_instance()
49 */
50 protected static $instance = NULL;
51
52 /**
53 * Constructor
54 */
55 public function __construct() {}
56
57 /**
58 * Used to access the instance
59 *
60 * @return object - class instance
61 */
62 public static function get_instance() {
63 if (NULL === self::$instance) self::$instance = new self();
64 return self::$instance;
65 }
66
67 /**
68 * Setup
69 */
70 public function setup() {
71 define('METASLIDER_PATH', plugin_dir_path(__FILE__));
72
73 $this->includes();
74 $this->define_constants();
75 $this->setup_actions();
76 $this->setup_filters();
77 $this->setup_shortcode();
78
79 // Load in slideshow admin relates classes.
80 $this->register_slide_types();
81 $this->admin = new MetaSlider_Admin_Pages($this);
82
83 // Load in slideshow related classes
84 require_once(METASLIDER_PATH . 'admin/slideshows/bootstrap.php');
85 $this->themes = MetaSlider_Themes::get_instance();
86
87 // Default to WP (4.4) REST API but backup with admin ajax
88 require_once(METASLIDER_PATH . 'admin/routes/api.php');
89 $api = MetaSlider_Api::get_instance();
90 $api->setup();
91 $api->register_admin_ajax_hooks();
92 if (class_exists('WP_REST_Controller')) new MetaSlider_REST_Controller();
93
94 if (function_exists('register_block_type')) {
95 $this->gutenberg = new MetaSlider_Gutenberg($this);
96 }
97 }
98
99 /**
100 * Define MetaSlider constants
101 */
102 private function define_constants() {
103 if (!defined('METASLIDER_VERSION')) {
104 define('METASLIDER_VERSION', $this->version);
105 define('METASLIDER_BASE_URL', trailingslashit(plugin_dir_url(metaslider_plugin_is_installed('ml-slider'))));
106 define('METASLIDER_ASSETS_URL', trailingslashit(METASLIDER_BASE_URL . 'assets'));
107 define('METASLIDER_ADMIN_URL', trailingslashit(METASLIDER_BASE_URL . 'admin'));
108
109 // Use the themes in the plugin dir if it's there (useful for developing)
110 if (file_exists(trailingslashit(WP_PLUGIN_DIR) . 'ml-slider-themes/manifest.php')) {
111 define('METASLIDER_THEMES_PATH', trailingslashit(WP_PLUGIN_DIR) . 'ml-slider-themes/');
112 define('METASLIDER_THEMES_URL', trailingslashit(plugins_url('ml-slider-themes/')));
113 } else {
114 define('METASLIDER_THEMES_PATH', trailingslashit(METASLIDER_PATH . 'themes/'));
115 define('METASLIDER_THEMES_URL', trailingslashit(METASLIDER_BASE_URL . 'themes/'));
116 }
117 }
118 }
119
120 /**
121 * All MetaSlider classes
122 */
123 private function plugin_classes() {
124 return array(
125 'metaslider' => METASLIDER_PATH . 'inc/slider/metaslider.class.php',
126 'metacoinslider' => METASLIDER_PATH . 'inc/slider/metaslider.coin.class.php',
127 'metaflexslider' => METASLIDER_PATH . 'inc/slider/metaslider.flex.class.php',
128 'metanivoslider' => METASLIDER_PATH . 'inc/slider/metaslider.nivo.class.php',
129 'metaresponsiveslider' => METASLIDER_PATH . 'inc/slider/metaslider.responsive.class.php',
130 'metaslide' => METASLIDER_PATH . 'inc/slide/metaslide.class.php',
131 'metaimageslide' => METASLIDER_PATH . 'inc/slide/metaslide.image.class.php',
132 'metasliderimagehelper' => METASLIDER_PATH . 'inc/metaslider.imagehelper.class.php',
133 'metaslidersystemcheck' => METASLIDER_PATH . 'inc/metaslider.systemcheck.class.php',
134 'metaslider_widget' => METASLIDER_PATH . 'inc/metaslider.widget.class.php',
135 'simple_html_dom' => METASLIDER_PATH . 'inc/simple_html_dom.php',
136 'metaslider_notices' => METASLIDER_PATH . 'admin/Notices.php',
137 'metaslider_admin_pages' => METASLIDER_PATH . 'admin/Pages.php',
138 'metaslider_slideshows' => METASLIDER_PATH . 'admin/Slideshows/Slideshows.php',
139 'metaslider_themes' => METASLIDER_PATH . 'admin/Slideshows/Themes.php',
140 'metaslider_tour' => METASLIDER_PATH . 'admin/Tour.php',
141 'metaslider_gutenberg' => METASLIDER_PATH . 'admin/Gutenberg.php'
142 );
143 }
144
145 /**
146 * Load required classes
147 */
148 private function includes() {
149 require_once(METASLIDER_PATH . 'admin/lib/helpers.php');
150 // require_once(METASLIDER_PATH . 'admin/lib/temporary.php');
151 $autoload_is_disabled = defined( 'METASLIDER_AUTOLOAD_CLASSES' ) && METASLIDER_AUTOLOAD_CLASSES === false;
152 if ( function_exists( "spl_autoload_register" ) && ! ( $autoload_is_disabled ) ) {
153
154 // >= PHP 5.2 - Use auto loading
155 if ( function_exists( "__autoload" ) ) {
156 spl_autoload_register( "__autoload" );
157 }
158
159 spl_autoload_register( array( $this, 'autoload' ) );
160
161 } else {
162
163 // < PHP5.2 - Require all classes
164 foreach ( $this->plugin_classes() as $id => $path ) {
165 if ( is_readable( $path ) && ! class_exists( $id ) ) {
166 require_once( $path );
167 }
168 }
169
170 }
171
172 }
173
174
175 /**
176 * Autoload MetaSlider classes to reduce memory consumption
177 *
178 * @param string $class Class name
179 */
180 public function autoload( $class ) {
181
182 $classes = $this->plugin_classes();
183
184 $class_name = strtolower( $class );
185
186 if ( isset( $classes[$class_name] ) && is_readable( $classes[$class_name] ) ) {
187 require_once( $classes[$class_name] );
188 }
189
190 }
191
192
193 /**
194 * Register the [metaslider] shortcode.
195 */
196 private function setup_shortcode() {
197
198 add_shortcode( 'metaslider', array( $this, 'register_shortcode' ) );
199 add_shortcode( 'ml-slider', array( $this, 'register_shortcode' ) ); // backwards compatibility
200
201 }
202
203
204 /**
205 * Hook MetaSlider into WordPress
206 */
207 private function setup_actions() {
208 add_action('admin_menu', array($this, 'register_admin_pages'), 9553);
209 add_action('init', array($this, 'register_post_types'));
210 add_action('init', array($this, 'register_taxonomy'));
211 add_action('init', array($this, 'load_plugin_textdomain'));
212 add_action('admin_footer', array($this, 'admin_footer'), 11);
213 add_action('widgets_init', array($this, 'register_metaslider_widget'));
214
215 add_action('admin_post_metaslider_preview', array($this, 'do_preview'));
216 add_action('admin_post_metaslider_switch_view', array($this, 'switch_view'));
217 add_action('admin_post_metaslider_delete_slide', array($this, 'delete_slide'));
218 add_action('admin_post_metaslider_delete_slider', array($this, 'delete_slider'));
219 add_action('admin_post_metaslider_create_slider', array($this, 'create_slider'));
220 add_action('admin_post_metaslider_update_slider', array($this, 'update_slider'));
221
222 add_action('media_upload_vimeo', array($this, 'upgrade_to_pro_tab_vimeo'));
223 add_action('media_upload_youtube', array($this, 'upgrade_to_pro_tab_youtube'));
224 add_action('media_upload_post_feed', array($this, 'upgrade_to_pro_tab_post_feed'));
225 add_action('media_upload_layer', array($this, 'upgrade_to_pro_tab_layer'));
226
227 // TODO: Refactor to Slide class object
228 add_action('wp_ajax_delete_slide', array($this, 'ajax_delete_slide'));
229 add_action('wp_ajax_undelete_slide', array($this, 'ajax_undelete_slide'));
230
231 // TODO: Make this work
232 // register_activation_hook(plugin_basename(__FILE__), array($this, 'after_activation'));
233 }
234
235
236 /**
237 * Hook MetaSlider into WordPress
238 */
239 private function setup_filters() {
240 add_filter('media_upload_tabs', array($this, 'custom_media_upload_tab_name'), 998);
241 add_filter('media_view_strings', array($this, 'custom_media_uploader_tabs'), 5);
242 add_filter('media_buttons_context', array($this, 'insert_metaslider_button'));
243 add_filter("plugin_row_meta", array($this, 'get_extra_meta_links'), 10, 4);
244 add_action('admin_head', array($this, 'add_star_styles'));
245 add_action('admin_head', array($this, 'add_tour_nonce_to_activation_page'));
246
247 // html5 compatibility for stylesheets enqueued within <body>
248 add_filter('style_loader_tag', array($this, 'add_property_attribute_to_stylesheet_links'), 11, 2);
249 }
250
251
252 /**
253 * Register MetaSlider widget
254 */
255 public function register_metaslider_widget() {
256 register_widget('MetaSlider_Widget');
257 }
258
259
260 /**
261 * Register ML Slider post type
262 */
263 public function register_post_types() {
264
265 $show_ui = false;
266
267 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
268
269 if ( is_admin() && current_user_can( $capability ) && ( isset($_GET['show_ui']) || defined("METASLIDER_DEBUG") && METASLIDER_DEBUG ) ) {
270 $show_ui = true;
271 }
272
273 register_post_type( 'ml-slider', array(
274 'query_var' => false,
275 'rewrite' => false,
276 'public' => false,
277 'exclude_from_search' => true,
278 'publicly_queryable' => false,
279 'show_in_nav_menus' => false,
280 'show_ui' => $show_ui,
281 'labels' => array(
282 'name' => 'MetaSlider'
283 )
284 )
285 );
286
287 register_post_type( 'ml-slide', array(
288 'query_var' => false,
289 'rewrite' => false,
290 'public' => false,
291 'exclude_from_search' => true,
292 'publicly_queryable' => false,
293 'show_in_nav_menus' => false,
294 'show_ui' => $show_ui,
295 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt'),
296 'labels' => array(
297 'name' => 'Meta Slides'
298 )
299 )
300 );
301
302 }
303
304
305 /**
306 * Register taxonomy to store slider => slides relationship
307 */
308 public function register_taxonomy() {
309
310 $show_ui = false;
311
312 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
313
314 if (is_admin() && current_user_can( $capability ) && ( isset($_GET['show_ui']) || defined("METASLIDER_DEBUG") && METASLIDER_DEBUG ) ) {
315 $show_ui = true;
316 }
317
318 register_taxonomy( 'ml-slider', array('attachment', 'ml-slide'), array(
319 'hierarchical' => true,
320 'public' => false,
321 'query_var' => false,
322 'rewrite' => false,
323 'show_ui' => $show_ui,
324 'label' => "Slider"
325 )
326 );
327
328 }
329
330
331 /**
332 * Register our slide types
333 */
334 private function register_slide_types() {
335
336 $image = new MetaImageSlide();
337
338 }
339
340 /**
341 * Add the menu pages
342 */
343 public function register_admin_pages() {
344 if (metaslider_pro_is_active()) {
345 $this->admin->add_page('MetaSlider Pro', 'metaslider');
346 } else {
347 $this->admin->add_page('MetaSlider');
348 }
349
350 if (metaslider_user_sees_upgrade_page()) {
351 $this->admin->add_page(__('Add-ons', 'ml-slider'), 'upgrade', 'metaslider');
352 }
353 }
354
355 /**
356 * Shortcode used to display slideshow
357 *
358 * @param string $atts attributes for short code
359 * @return string HTML output of the shortcode
360 */
361 public function register_shortcode($atts) {
362 extract(shortcode_atts(array(
363 'id' => false,
364 'title' => false,
365 'restrict_to' => false,
366 'theme' => null
367 ), $atts, 'metaslider'));
368
369 // If no id and no title, exit here
370 if (!$id && !$title) return false;
371
372 // If there is a title, get the id from the title
373 if ($title) {
374 global $wpdb;
375
376 // Run a custom query because get_page_by_title() includes "trash" posts
377 // Also, be sure just to get 1 post, in case they have multiple
378 $sql = $wpdb->prepare("
379 SELECT ID
380 FROM $wpdb->posts
381 WHERE post_title = %s
382 AND post_type = 'ml-slider'
383 AND post_status = 'publish'
384 LIMIT 1
385 ", $title);
386 $id = $wpdb->get_var($sql);
387
388 // If no posts were returned, $id will be NULL
389 if (is_null($id) || !(bool) $title) return false;
390 }
391
392 // handle [metaslider id=123 restrict_to=home]
393 if ($restrict_to && ('home' === $restrict_to) && !is_front_page()) return false;
394 if ($restrict_to && ('home' !== $restrict_to) && !is_page($restrict_to)) return false;
395
396 // Attempt to get the ml-slider post object
397 $slider = get_post($id);
398
399 // check the slideshow is published and the ID is correct
400 if (!$slider || 'publish' !== $slider->post_status || 'ml-slider' !== $slider->post_type) {
401 return "<!-- MetaSlider {$atts['id']} not found -->";
402 }
403
404 // Set up the slideshow and load the slideshow theme
405 $this->set_slider($id, $atts);
406 MetaSlider_Themes::get_instance()->load_theme($id, $theme);
407 $this->slider->enqueue_scripts();
408 return $this->slider->render_public_slides();
409 }
410
411 /**
412 * Set first activation option to database
413 */
414 public function after_activation() {
415
416 // Set date showing the first activation and redirect
417 if (!get_option('ms_was_installed_on')) {
418 update_option('ms_was_installed_on', time());
419 }
420 }
421
422 /**
423 * Initialise translations
424 */
425 public function load_plugin_textdomain() {
426
427 load_plugin_textdomain( 'ml-slider', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
428
429 }
430
431
432 /**
433 * Outputs a blank page containing a slideshow preview (for use in the 'Preview' iFrame)
434 */
435 public function do_preview() {
436
437 remove_action('wp_footer', 'wp_admin_bar_render', 1000);
438
439 if ( isset( $_GET['slider_id'] ) && absint( $_GET['slider_id'] ) > 0 ) {
440 $id = absint( $_GET['slider_id'] );
441
442 ?>
443 <!DOCTYPE html>
444 <html>
445 <head>
446 <style type='text/css'>
447 body, html {
448 overflow: hidden;
449 margin: 0;
450 padding: 0;
451 }
452 </style>
453 <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
454 <meta http-equiv="Pragma" content="no-cache" />
455 <meta http-equiv="Expires" content="0" />
456 </head>
457 <body>
458 <?php echo do_shortcode("[metaslider id={$id}]"); ?>
459 <?php wp_footer(); ?>
460 </body>
461 </html>
462 <?php
463 }
464
465 die();
466
467 }
468
469
470 /**
471 * Check our WordPress installation is compatible with MetaSlider
472 */
473 public function do_system_check() {
474
475 $systemCheck = new MetaSliderSystemCheck();
476 $systemCheck->check();
477
478 }
479
480
481 /**
482 * Update the tab options in the media manager
483 *
484 * @param array $strings Array of settings for custom media tabs
485 * @return array
486 */
487 public function custom_media_uploader_tabs( $strings ) {
488
489 // update strings
490 if ( ( isset( $_GET['page'] ) && $_GET['page'] == 'metaslider' ) ) {
491 $strings['insertMediaTitle'] = __( "Image", "ml-slider" );
492 $strings['insertIntoPost'] = __( "Add to slideshow", "ml-slider" );
493
494 // remove options
495 $strings_to_remove = array(
496 'createVideoPlaylistTitle',
497 'createGalleryTitle',
498 'insertFromUrlTitle',
499 'createPlaylistTitle'
500 );
501
502 foreach ($strings_to_remove as $string) {
503 if (isset($strings[$string])) {
504 unset($strings[$string]);
505 }
506 }
507 }
508
509 return $strings;
510
511 }
512
513
514 /**
515 * Add extra tabs to the default wordpress Media Manager iframe
516 *
517 * @param array $tabs existing media manager tabs]
518 * @return array
519 */
520 public function custom_media_upload_tab_name( $tabs ) {
521
522 $metaslider_tabs = array( 'post_feed', 'layer', 'youtube', 'vimeo' );
523
524 // restrict our tab changes to the MetaSlider plugin page
525 if ( ( isset( $_GET['page'] ) && $_GET['page'] == 'metaslider' ) || ( isset( $_GET['tab'] ) && in_array( $_GET['tab'], $metaslider_tabs ) ) ) {
526 $newtabs = array();
527
528 if ( function_exists( 'is_plugin_active' ) && ! is_plugin_active( 'ml-slider-pro/ml-slider-pro.php' ) ) {
529 $newtabs = array(
530 'post_feed' => __( "Post Feed", "metaslider" ),
531 'vimeo' => __( "Vimeo", "metaslider" ),
532 'youtube' => __( "YouTube", "metaslider" ),
533 'layer' => __( "Layer Slide", "metaslider" )
534 );
535 }
536
537 if ( isset( $tabs['nextgen'] ) )
538 unset( $tabs['nextgen'] );
539
540
541 if ( is_array( $tabs ) ) {
542 return array_merge( $tabs, $newtabs );
543 } else {
544 return $newtabs;
545 }
546
547 }
548
549 return $tabs;
550
551
552 }
553
554 /**
555 * Set the current slider
556 *
557 * @param int $id ID for slider
558 * @param array $shortcode_settings Settings for slider
559 */
560 public function set_slider( $id, $shortcode_settings = array() ) {
561
562 $type = 'flex';
563
564 if ( isset( $shortcode_settings['type'] ) ) {
565 $type = $shortcode_settings['type'];
566 } else if ( $settings = get_post_meta( $id, 'ml-slider_settings', true ) ) {
567 if ( is_array( $settings ) && isset( $settings['type'] ) ) {
568 $type = $settings['type'];
569 }
570 }
571
572 if ( ! in_array( $type, array( 'flex', 'coin', 'nivo', 'responsive' ) ) ) {
573 $type = 'flex';
574 }
575
576 $this->slider = $this->load_slider( $type, $id, $shortcode_settings );
577
578 }
579
580
581 /**
582 * Create a new slider based on the sliders type setting
583 *
584 * @param string $type Type of slide
585 * @param int $id ID of slide
586 * @param string $shortcode_settings Shortcode settings
587 * @return array
588 */
589 private function load_slider( $type, $id, $shortcode_settings ) {
590
591 switch ( $type ) {
592 case( 'coin' ):
593 return new MetaCoinSlider( $id, $shortcode_settings );
594 case( 'flex' ):
595 return new MetaFlexSlider( $id, $shortcode_settings );
596 case( 'nivo' ):
597 return new MetaNivoSlider( $id, $shortcode_settings );
598 case( 'responsive' ):
599 return new MetaResponsiveSlider( $id, $shortcode_settings );
600 default:
601 return new MetaFlexSlider( $id, $shortcode_settings );
602
603 }
604 }
605
606 /**
607 * Update the slider
608 *
609 * @return string a JSON string with success or failure (and errors)
610 */
611 public function update_slider() {
612
613 // Wordpress will just die() if this fails
614 check_admin_referer("metaslider_update_slider");
615
616 if (!current_user_can(apply_filters('metaslider_capability', 'edit_others_posts'))) {
617 return wp_send_json_error(array(
618 'message' => __('The security check failed. Please refresh the page and try again.', 'ml-slider')
619 ), 401);
620 }
621
622 $slider_id = absint($_POST['slider_id']);
623 if (!$slider_id) {
624 return wp_send_json_error(array(
625 'message' => __("The slideshow you're trying to update was not found.", 'ml-slider')
626 ), 401);
627 }
628
629 $errors = new WP_Error();
630
631 // update settings
632 if (isset($_POST['settings'])) {
633 $new_settings = $_POST['settings'];
634 $old_settings = get_post_meta($slider_id, 'ml-slider_settings', true);
635
636 // convert submitted checkbox values from 'on' or 'off' to boolean values
637 $checkboxes = apply_filters("metaslider_checkbox_settings", array('noConflict', 'fullWidth', 'hoverPause', 'links', 'reverse', 'random', 'printCss', 'printJs', 'smoothHeight', 'center', 'carouselMode', 'autoPlay', 'firstSlideFadeIn', 'responsive_thumbs'));
638
639 foreach ($checkboxes as $checkbox) {
640 $new_settings[$checkbox] = (isset($new_settings[$checkbox]) && 'on' == $new_settings[$checkbox]) ? 'true' : 'false';
641 }
642
643 $settings = array_merge((array) $old_settings, $new_settings);
644
645 // update the slider settings
646 // TODO this will return false if the data is unchanged, so we should consider checking the data prior to updating it.
647 $result = update_post_meta($slider_id, 'ml-slider_settings', $settings);
648 // if (!$result) $errors->add('update_failed', __('There was an error while updating the post meta. Most likely this means nothing has changed.', 'ml-slider'));
649 }
650
651 // update slideshow title
652 if (isset($_POST['title'])) {
653 $result = wp_update_post(array(
654 'ID' => $slider_id,
655 'post_title' => esc_html($_POST['title'])
656 ));
657 if (!$result) $errors->add('update_failed', __('There was an error while updating the title.', 'ml-slider'));
658 }
659
660 // update individual slides
661 // TODO Refactor this to return better error handling.
662 if (isset($_POST['attachment'])) {
663 foreach ($_POST['attachment'] as $slide_id => $fields) {
664 do_action("metaslider_save_{$fields['type']}_slide", $slide_id, $slider_id, $fields);
665 }
666 }
667
668 if (count($errors->get_error_messages())) {
669 return wp_send_json_error($errors, 409);
670 }
671
672 return wp_send_json_success(array(
673 'message' => __('The slideshow was successfully updated.', 'ml-slider'),
674 ), 200);
675 }
676
677 /**
678 * Delete a slide via ajax.
679 *
680 * @return string Returns the status of the request
681 */
682 public function ajax_undelete_slide() {
683 if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'metaslider_undelete_slide')) {
684 return wp_send_json_error(array(
685 'message' => __('The security check failed. Please refresh the page and try again.', 'ml-slider')
686 ), 401);
687 }
688
689 $result = $this->undelete_slide(absint($_POST['slide_id']), absint($_POST['slider_id']));
690
691 if (is_wp_error($result)) {
692 return wp_send_json_error(array(
693 'message' => $result->get_error_message()
694 ), 409);
695 }
696
697 return wp_send_json_success(array(
698 'message' => __('The slide was successfully restored', 'ml-slider'),
699 ), 200);
700 }
701
702 /**
703 * Undeletes a slide.
704 *
705 * @param int $slide_id The ID of the slide
706 * @param int $slider_id The ID of the slider (for legacy purposes)
707 * @return mixed
708 */
709 public function undelete_slide($slide_id, $slider_id) {
710 if ('ml-slide' === get_post_type($slide_id)) {
711 return wp_update_post(array(
712 'ID' => $slide_id,
713 'post_status' => 'publish'
714 ), new WP_Error('update_failed', __('The attempt to restore the slide failed.', 'ml-slider'), array('status' => 409)));
715 }
716
717 /*
718 * Legacy: This removes the relationship between the slider and slide
719 * This restores the relationship between a slide and slider.
720 * If using a newer version, this relationship is never lost on delete.
721 */
722
723 // Get the slider's term and apply it to the slide.
724 $term = get_term_by('name', $slider_id, 'ml-slider');
725 return wp_set_object_terms($slide_id, $term->term_id, 'ml-slider');
726 }
727
728 /**
729 * Delete a slide via ajax.
730 */
731 public function ajax_delete_slide() {
732 if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'metaslider_delete_slide')) {
733 return wp_send_json_error(array(
734 'message' => __('The security check failed. Please refresh the page and try again.', 'ml-slider')
735 ), 401);
736 }
737
738 $result = $this->delete_slide(absint($_POST['slide_id']), absint($_POST['slider_id']));
739
740 if (is_wp_error($result)) {
741 return wp_send_json_error(array(
742 'message' => $result->get_error_message()
743 ), 409);
744 }
745
746 return wp_send_json_success(array(
747 'message' => __('The slide was successfully trashed', 'ml-slider'),
748 ), 200);
749 }
750
751 /**
752 * Delete a slide by either trashing it or for
753 * legacy reasons removing the taxonomy relationship.
754 *
755 * @param int $slide_id The ID of the slide
756 * @param int $slider_id The ID of the slider
757 * @return mixed Will return the terms or WP_Error
758 */
759 public function delete_slide($slide_id, $slider_id) {
760 if ('ml-slide' === get_post_type($slide_id)) {
761 return wp_update_post(array(
762 'ID' => $slide_id,
763 'post_status' => 'trash'
764 ), new WP_Error('update_failed', 'The attempt to delete the slide failed.', array('status' => 409)));
765 }
766
767 /*
768 * Legacy: This removes the relationship between the slider and slide
769 * A slider with ID 216 might have a term_id of 7
770 * A slide with ID 217 could have a term_taxonomy_id of 7
771 * Multiple slides would have this term_taxonomy_id of 7
772 */
773
774 // This returns the term_taxonomy_id (7 from example)
775 $current_terms = wp_get_object_terms($slide_id, 'ml-slider', array('fields' => 'ids'));
776
777 // This returns the term object, named after the slider ID
778 // The $term->term_id would be 7 in the example above
779 // It also includes the count of slides attached to the slider
780 $term = get_term_by('name', $slider_id, 'ml-slider');
781
782 // I'm not sure why this is here. It seems this is only useful if
783 // a slide was attached to multiple sliders. A slide should only
784 // have one $current_terms (7 above)
785 $new_terms = array();
786 foreach ($current_terms as $current_term) {
787 if ($current_term != $term->term_id) {
788 $new_terms[] = absint($current_term);
789 }
790 }
791
792 // This only works becasue $new_terms is an empty array,
793 // which deletes the relationship. I'm leaving the loop above
794 // in case it's here for some legacy reason I'm unaware of.
795 return wp_set_object_terms($slide_id, $new_terms, 'ml-slider');
796 }
797
798
799 /**
800 * Delete a slider (send it to trash)
801 */
802 public function delete_slider() {
803
804 // check nonce
805 check_admin_referer( "metaslider_delete_slider" );
806
807 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
808
809 if ( ! current_user_can( $capability ) ) {
810 return;
811 }
812
813 $slider_id = absint( $_GET['slider_id'] );
814
815 if ( get_post_type( $slider_id ) != 'ml-slider' ) {
816 wp_redirect( admin_url( "admin.php?page=metaslider" ) );
817 wp_die();
818 }
819
820 // send the post to trash
821 $id = wp_update_post( array(
822 'ID' => $slider_id,
823 'post_status' => 'trash'
824 )
825 );
826
827 $this->delete_all_slides_from_slider($slider_id);
828
829 $slider_id = $this->find_slider( 'modified', 'DESC' );
830
831 wp_redirect( admin_url( "admin.php?page=metaslider&id={$slider_id}" ) );
832
833 }
834
835
836 /**
837 * Trashes all new format slides for a given slideshow ID
838 *
839 * @param int $slider_id Specified Slider ID
840 * @return int - The ID of the slideshow from which the slides were removed
841 */
842 private function delete_all_slides_from_slider($slider_id) {
843 // find slides and trash them
844 $args = array(
845 'force_no_custom_order' => true,
846 'orderby' => 'menu_order',
847 'order' => 'ASC',
848 'post_type' => array('ml-slide'),
849 'post_status' => array('publish'),
850 'lang' => '', // polylang, ingore language filter
851 'suppress_filters' => 1, // wpml, ignore language filter
852 'posts_per_page' => -1,
853 'tax_query' => array(
854 array(
855 'taxonomy' => 'ml-slider',
856 'field' => 'slug',
857 'terms' => $slider_id
858 )
859 )
860 );
861
862 $query = new WP_Query( $args );
863
864 while ( $query->have_posts() ) {
865 $query->next_post();
866 $id = $query->post->ID;
867
868 $id = wp_update_post( array(
869 'ID' => $id,
870 'post_status' => 'trash'
871 )
872 );
873 }
874
875 return $slider_id;
876 }
877
878
879 /**
880 * Switch view
881 *
882 * @return null
883 */
884 public function switch_view() {
885 global $user_ID;
886
887 $view = $_GET['view'];
888
889 $allowed_views = array('tabs', 'dropdown');
890
891 if ( ! in_array( $view, $allowed_views ) ) {
892 return;
893 }
894
895 delete_user_meta( $user_ID, "metaslider_view" );
896
897 if ( $view == 'dropdown' ) {
898 add_user_meta( $user_ID, "metaslider_view", "dropdown");
899 }
900
901 wp_redirect( admin_url( "admin.php?page=metaslider" ) );
902
903 }
904
905
906 /**
907 * Create a new slider
908 */
909 public function create_slider() {
910
911 // check nonce
912 check_admin_referer( "metaslider_create_slider" );
913
914 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
915
916 if ( ! current_user_can( $capability ) ) {
917 return;
918 }
919
920 $defaults = array();
921
922 // if possible, take a copy of the last edited slider settings in place of default settings
923 if ( $last_modified = $this->find_slider( 'modified', 'DESC' ) ) {
924 $defaults = get_post_meta( $last_modified, 'ml-slider_settings', true );
925 }
926
927 // insert the post
928 $id = wp_insert_post( array(
929 'post_title' => __("New Slideshow", "ml-slider"),
930 'post_status' => 'publish',
931 'post_type' => 'ml-slider'
932 )
933 );
934
935 // use the default settings if we can't find anything more suitable.
936 if ( empty( $defaults ) ) {
937 $slider = new MetaSlider( $id, array() );
938 $defaults = $slider->get_default_parameters();
939 }
940
941 // insert the post meta
942 add_post_meta( $id, 'ml-slider_settings', $defaults, true );
943
944 // create the taxonomy term, the term is the ID of the slider itself
945 wp_insert_term( $id, 'ml-slider' );
946
947 wp_redirect( admin_url( "admin.php?page=metaslider&id={$id}" ) );
948
949 }
950
951
952
953 /**
954 * Find a single slider ID. For example, last edited, or first published.
955 *
956 * @param string $orderby field to order.
957 * @param string $order direction (ASC or DESC).
958 * @return int slider ID.
959 */
960 private function find_slider( $orderby, $order ) {
961
962 $args = array(
963 'force_no_custom_order' => true,
964 'post_type' => 'ml-slider',
965 'num_posts' => 1,
966 'post_status' => 'publish',
967 'suppress_filters' => 1, // wpml, ignore language filter
968 'orderby' => $orderby,
969 'order' => $order
970 );
971
972 $the_query = new WP_Query( $args );
973
974 while ( $the_query->have_posts() ) {
975 $the_query->the_post();
976 return $the_query->post->ID;
977 }
978
979 wp_reset_query();
980
981 return false;
982
983 }
984
985
986 /**
987 * Get sliders. Returns a nicely formatted array of currently
988 * published sliders.
989 *
990 * @param string $sort_key Specified sort key
991 * @return array all published sliders
992 */
993 public function all_meta_sliders( $sort_key = 'date' ) {
994
995 $sliders = array();
996
997 // list the tabs
998 $args = array(
999 'post_type' => 'ml-slider',
1000 'post_status' => 'publish',
1001 'orderby' => $sort_key,
1002 'suppress_filters' => 1, // wpml, ignore language filter
1003 'order' => 'ASC',
1004 'posts_per_page' => -1
1005 );
1006
1007 $args = apply_filters( 'metaslider_all_meta_sliders_args', $args );
1008
1009 // WP_Query causes issues with other plugins using admin_footer to insert scripts
1010 // use get_posts instead
1011 $all_sliders = get_posts( $args );
1012
1013 foreach( $all_sliders as $slideshow ) {
1014
1015 $active = $this->slider && ( $this->slider->id == $slideshow->ID ) ? true : false;
1016
1017 $sliders[] = array(
1018 'active' => $active,
1019 'title' => $slideshow->post_title,
1020 'id' => $slideshow->ID
1021 );
1022
1023 }
1024
1025 return $sliders;
1026
1027 }
1028
1029
1030 /**
1031 * Compare array values
1032 *
1033 * @param array $elem1 The first element to comapre
1034 * @param array $elem2 The second element to comapr
1035 * @return bool
1036 */
1037 private function compare_elems( $elem1, $elem2 ) {
1038
1039 return $elem1['priority'] > $elem2['priority'];
1040
1041 }
1042
1043
1044 /**
1045 * Building setting rows
1046 *
1047 * @param array $settings array of fields to render
1048 * @return string
1049 */
1050 public function build_settings_rows($settings) {
1051
1052 // order the fields by priority
1053 uasort($settings, array($this, "compare_elems"));
1054 $output = "";
1055
1056 // loop through the array and build the settings HTML
1057 foreach ($settings as $id => $row) {
1058 $helptext = isset($row['helptext']) ? htmlentities2($row['helptext']) : '';
1059
1060 switch ($row['type']) {
1061
1062 // checkbox input type
1063 case 'checkbox':
1064 $output .= "<tr><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><input class='option {$row['class']} {$id}' type='checkbox' name='settings[{$id}]' {$row['checked']} />";
1065 if (isset($row['after'])) {
1066 $output .= "<span class='after'>{$row['after']}</span>";
1067 }
1068 $output .= "</td></tr>";
1069 break;
1070
1071 // navigation row
1072 case 'navigation':
1073 $navigation_row = "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><ul>";
1074 foreach ($row['options'] as $option_name => $option_value) {
1075 $tease = isset($option_value['addon_required']) ? 'disabled' : '';
1076 if (true === $row['value'] && 'true' === $option_name) {
1077 $checked = checked(true, true, false);
1078 } else if (false === $row['value'] && 'false' === $option_name) {
1079 $checked = checked(true, true, false);
1080 } else {
1081 $checked = checked($option_name, $row['value'], false);
1082 }
1083 $disabled = $option_name == 'thumbnails' ? 'disabled' : '';
1084 $navigation_row .= "<li><label class='{$tease}'><input {$tease} type='radio' name='settings[{$id}]' value='{$option_name}' {$checked} {$disabled}/>{$option_value['label']}</label>";
1085 if (isset($option_value['addon_required']) && $option_value['addon_required']) {
1086 $navigation_row .= sprintf(" <a target='_blank' class='get-addon' href='%s' title='%s'>%s</a>", metaslider_get_upgrade_link(), __('Get the Add-on Pack today!', 'ml-slider'), __('Learn More', 'ml-slider'));
1087 }
1088 $navigation_row .= "</li>";
1089 }
1090 $navigation_row .= "</ul></td></tr>";
1091 $output .= apply_filters('metaslider_navigation_options', $navigation_row, $this->slider);
1092 break;
1093
1094 // navigation row
1095 case 'radio':
1096 $navigation_row = "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><ul>";
1097 foreach ($row['options'] as $option_name => $option_value) {
1098 $checked = checked($option_name, $row['value'], false);
1099 $class = isset($option_value['class']) ? $option_value['class'] : "";
1100 $navigation_row .= "<li><label><input type='radio' name='settings[{$id}]' value='{$option_name}' {$checked} class='radio {$class}'/>{$option_value['label']}</label></li>";
1101 }
1102 $navigation_row .= "</ul></td></tr>";
1103 $output .= apply_filters('metaslider_navigation_options', $navigation_row, $this->slider);
1104 break;
1105
1106 // header/divider row
1107 case 'divider':
1108 $output .= "<tr class='{$row['type']}'><td colspan='2' class='divider'><b>{$row['value']}</b></td></tr>";
1109 break;
1110
1111 // slideshow select row
1112 case 'slider-lib':
1113 $output .= "<tr class='{$row['type']}'><td colspan='2' class='slider-lib-row'>";
1114 foreach ($row['options'] as $option_name => $option_value) {
1115 $checked = checked($option_name, $row['value'], false);
1116 $output .= "<input class='select-slider' id='{$option_name}' rel='{$option_name}' type='radio' name='settings[type]' value='{$option_name}' {$checked} />
1117 <label tabindex='0' for='{$option_name}'>{$option_value['label']}</label>";
1118 }
1119 $output .= "</td></tr>";
1120 break;
1121
1122 // number input type
1123 case 'number':
1124 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><input class='option {$row['class']} {$id}' type='number' min='{$row['min']}' max='{$row['max']}' step='{$row['step']}' name='settings[{$id}]' value='" . absint($row['value']) . "' /><span class='after'>{$row['after']}</span></td></tr>";
1125 break;
1126
1127 // select drop down
1128 case 'select':
1129 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><select class='option {$row['class']} {$id}' name='settings[{$id}]'>";
1130 foreach ($row['options'] as $option_name => $option_value) {
1131 $selected = selected($option_name, $row['value'], false);
1132 $output .= "<option class='{$option_value['class']}' value='{$option_name}' {$selected}>{$option_value['label']}</option>";
1133 }
1134 $output .= "</select></td></tr>";
1135 break;
1136
1137 // theme drop down
1138 case 'theme':
1139 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><select class='option {$row['class']} {$id}' name='settings[{$id}]'>";
1140 $themes = "";
1141 foreach ($row['options'] as $option_name => $option_value) {
1142 $selected = selected($option_name, $row['value'], false);
1143 $themes .= "<option class='{$option_value['class']}' value='{$option_name}' {$selected}>{$option_value['label']}</option>";
1144 }
1145 $output .= apply_filters('metaslider_get_available_themes', $themes, $this->slider->get_setting('theme'));
1146 $output .= "</select></td></tr>";
1147 break;
1148
1149 // text input type
1150 case 'text':
1151 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><input class='option {$row['class']} {$id}' type='text' name='settings[{$id}]' value='" . esc_attr($row['value']) . "' /></td></tr>";
1152 break;
1153
1154 // text input type
1155 case 'textarea':
1156 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}' colspan='2'>{$row['label']}</td></tr><tr><td colspan='2'><textarea class='option {$row['class']} {$id}' name='settings[{$id}]' />{$row['value']}</textarea></td></tr>";
1157 break;
1158
1159 // text input type
1160 case 'title':
1161 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><input class='option {$row['class']} {$id}' type='text' name='{$id}' value='" . esc_attr( $row['value']) . "' /></td></tr>";
1162 break;
1163 }
1164 }
1165 return $output;
1166 }
1167
1168
1169 /**
1170 * Return an indexed array of all easing options
1171 *
1172 * @return array
1173 */
1174 private function get_easing_options() {
1175
1176 $options = array(
1177 'linear', 'swing', 'jswing', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad',
1178 'easeInCubic', 'easeOutCubic', 'easeInOutCubic', 'easeInQuart',
1179 'easeOutQuart', 'easeInOutQuart', 'easeInQuint', 'easeOutQuint',
1180 'easeInOutQuint', 'easeInSine', 'easeOutSine', 'easeInOutSine',
1181 'easeInExpo', 'easeOutExpo', 'easeInOutExpo', 'easeInCirc', 'easeOutCirc',
1182 'easeInOutCirc', 'easeInElastic', 'easeOutElastic', 'easeInOutElastic',
1183 'easeInBack', 'easeOutBack', 'easeInOutBack', 'easeInBounce', 'easeOutBounce',
1184 'easeInOutBounce'
1185 );
1186 $output = array();
1187
1188 foreach ( $options as $option) {
1189 $output[$option] = array(
1190 'label' => ucfirst( preg_replace( '/(\w+)([A-Z])/U', '\\1 \\2', $option)),
1191 'class' => ''
1192 );
1193 }
1194
1195 return $output;
1196
1197 }
1198
1199 /**
1200 * Output the slideshow selector.
1201 *
1202 * Show tabs or a dropdown list depending on the users saved preference.
1203 */
1204 public function print_slideshow_selector() {
1205 global $user_ID;
1206
1207 // First check if we have any slideshows yet
1208 if ($tabs = $this->all_meta_sliders()) {
1209
1210 // Next check if they have the tabs view selected
1211 if ('tabs' == $this->get_view()) {
1212
1213 // Render the tabs
1214 echo "<div class='nav-tab-wrapper'>";
1215 foreach ($tabs as $tab) {
1216 if ( $tab['active'] ) {
1217 echo "<div class='nav-tab nav-tab-active'><input class='no_last_pass' type='text' name='title' value='" . esc_attr($tab['title']) . "'></div>";
1218 } else {
1219 echo "<a href='?page=metaslider&amp;id={$tab['id']}' title= '" . esc_attr($tab['title']) . "' class='nav-tab'>" . esc_html( $tab['title'] ) . "</a>";
1220 }
1221 }
1222 echo $this->get_add_slideshow_button("New", 'nav-tab');
1223 echo "</div>";
1224
1225 // This will render the select dropdown view
1226 // TODO make this resemble the WP Nav menu UI perhaps
1227 } else {
1228 echo "<div class='manage-menus'><label for='select-slideshow' class='selected-menu'>" . __("Select Slideshow", "ml-slider") . ": </label>";
1229 echo "<select name='select-slideshow' onchange='if (this.value) window.location.href=this.value'>";
1230
1231 $tabs = $this->all_meta_sliders('title');
1232 foreach ($tabs as $tab) {
1233 $selected = $tab['active'] ? " selected" : "";
1234 if ($tab['active']) {
1235 $title = $tab['title'];
1236 }
1237 echo "<option value='?page=metaslider&amp;id={$tab['id']}'{$selected}>{$tab['title']}</option>";
1238 }
1239 echo "</select>";
1240 echo "<span class='add-new-menu-action'> " . _x('or', 'Use this to separate one action from another action as in Select "or" Create', 'ml-slider') . " ";
1241 echo "<a href='". wp_nonce_url(admin_url("admin-post.php?action=metaslider_create_slider"), "metaslider_create_slider") ."' id='create_new_tab' class='' title='" . __('Create a New Slideshow', 'ml-slider') . "'>create a new slideshow</a>";
1242 echo "</span></div>";
1243 }
1244
1245 // This section is shown when there are no slideshows
1246 } else {
1247 echo "<div class='nav-tab-wrapper'>";
1248 echo "<div class='fake-tabs nav-tab nav-tab-active'><span class='blurred-out'>" . __('New Slideshow', 'ml-slider') ."</span></div>";
1249 echo $this->get_add_slideshow_button("New", 'nav-tab');
1250 echo "</div>";
1251 }
1252 }
1253
1254 /**
1255 * Return a button to sadd a new slideshow.
1256 *
1257 * @param string $text text for the button
1258 * @param string $classes Specify calsses for the button
1259 * @return sring HTMl Button
1260 */
1261 protected function get_add_slideshow_button($text = '', $classes = '') {
1262 $add_url = wp_nonce_url(admin_url("admin-post.php?action=metaslider_create_slider"), "metaslider_create_slider");
1263 if ('' == $text) {
1264 $text = __('Add a New Slideshow', 'ml-slider');
1265 }
1266 return "<a href='{$add_url}' id='create_new_tab' class='ml-add-new {$classes}' title='" . __('Add a New Slideshow', 'ml-slider') . "'><i><svg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-plus-circle'><circle cx='12' cy='12' r='10'/><line x1='12' y1='8' x2='12' y2='16'/><line x1='8' y1='12' x2='16' y2='12'/></svg></i> {$text}</a>";
1267 }
1268
1269 /**
1270 * Return the users saved view preference.
1271 */
1272 public function get_view() {
1273 global $user_ID;
1274
1275 if ( get_user_meta( $user_ID, "metaslider_view", true ) ) {
1276 return get_user_meta( $user_ID, "metaslider_view", true );
1277 }
1278
1279 return 'tabs';
1280 }
1281
1282
1283 /**
1284 * Render the admin page (tabs, slides, settings)
1285 */
1286 public function render_admin_page() {
1287
1288 // Default to the most recently modified slider
1289 $slider_id = $this->find_slider('modified', 'DESC');
1290
1291 // If the id parameter exists, verify and use that.
1292 if (isset($_REQUEST['id']) && $id = $_REQUEST['id']) {
1293 if (in_array(get_post_status(absint($id)), array('publish', 'inherit'))) {
1294 $slider_id = (int)$id;
1295 }
1296 }
1297
1298 // "Set the slider"
1299 // TODO figure out what this does and if it can be better stated
1300 // Perhaps maybe "apply_settings()" or something.
1301 if ($slider_id) {
1302 $this->set_slider($slider_id);
1303 }
1304
1305 echo "<div class='wrap metaslider-ui-top' style='margin-top:0;'>";
1306 echo $this->documentation_button();
1307 echo $this->toggle_layout_button();
1308
1309 if (metaslider_user_sees_call_to_action()) {
1310 echo $this->addons_page_button();
1311 echo $this->upgrade_to_pro_top_button();
1312 }
1313 echo "</div>";
1314
1315 $this->do_system_check();
1316
1317 $slider_id = $this->slider ? $this->slider->id : 0;
1318
1319 ?>
1320
1321 <script>
1322 var metaslider_slider_id = <?php echo $slider_id; ?>;
1323 </script>
1324
1325 <div id="metaslider-ui" class="metaslider metaslider-ui">
1326 <?php $slider_settings = get_post_meta($slider_id, 'ml-slider_settings', true); ?>
1327 <metaslider :id='<?php echo $slider_id; ?>' v-bind:settings='<?php echo json_encode($slider_settings);?>' inline-template>
1328 <div>
1329 <h1 class="wp-heading-inline metaslider-title">
1330 <img width=50 height=50 src="<?php echo METASLIDER_ADMIN_URL ?>images/metaslider_logo_large.png" alt="MetaSlider">
1331 MetaSlider
1332 <?php if (metaslider_pro_is_active()) {
1333 echo ' Pro';
1334 } ?>
1335 </h1>
1336 <?php if (metaslider_user_is_ready_for_notices()) {
1337 echo $this->notices->do_notice(false, 'header', true);
1338 } ?>
1339 <form accept-charset="UTF-8" action="<?php echo admin_url( 'admin-post.php'); ?>" method="post">
1340 <input type="hidden" name="action" value="metaslider_update_slider">
1341 <input type="hidden" name="slider_id" value="<?php echo $slider_id; ?>">
1342 <?php wp_nonce_field( 'metaslider_update_slider' ); ?>
1343
1344 <?php $this->print_slideshow_selector(); ?>
1345
1346 <?php // If there is no slideshow we don't need to show the rest
1347 if (!$this->slider) { echo '</form></div></metaslider>'; return false; } ?>
1348
1349 <div id='poststuff' class="metaslider-inner wp-clearfix">
1350 <div id='post-body' class='metabox-holder columns-2'>
1351
1352 <div id='post-body-content'>
1353 <div class="left">
1354
1355 <?php do_action( "metaslider_admin_table_before", $this->slider->id ); ?>
1356
1357 <table id="metaslider-slides-list" class="widefat sortable metaslider-slides-container">
1358 <thead>
1359 <tr>
1360 <?php if (metaslider_viewing_trashed_slides($this->slider->id)) {
1361
1362 // If they are on the trash page, show them?>
1363 <th class="trashed-header">
1364 <h3><i><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-trash-2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg></i> <?php _e('Trashed Slides', 'ml-slider'); ?></h3>
1365 <small> <?php printf(__('<a href="%s">view active</a>', 'ml-slider'), admin_url("?page=metaslider&id={$this->slider->id}")); ?></small>
1366 </th>
1367 <?php } else { ?>
1368 <th class="slider-title" colspan="2">
1369 <h3 class="alignleft"><?php echo get_the_title($this->slider->id) ?></h3>
1370 <?php if (!metaslider_viewing_trashed_slides($this->slider->id)) {
1371
1372 // Remove the actions on trashed view?>
1373 <button class='ml-button ml-has-icon ml-skinless-button alignright add-slide' data-editor='content' title='<?php _e( "Add a New Slide", "ml-slider" ) ?>'>
1374 <i style="top:0;"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg></i>
1375 <span><?php _e("Add Slide", "ml-slider") ?></span>
1376 </button>
1377 <?php } ?>
1378 <?php do_action( "metaslider_admin_table_header_right", $this->slider->id ); ?>
1379 </th>
1380 <?php } ?>
1381 </tr>
1382 </thead>
1383
1384 <tbody>
1385 <?php
1386 $this->slider->render_admin_slides();
1387 ?>
1388 </tbody>
1389 </table>
1390
1391 <?php do_action( "metaslider_admin_table_after", $this->slider->id ); ?>
1392
1393 </div>
1394 </div>
1395
1396 <div id="postbox-container-1" class="postbox-container ml-sidebar metaslider-settings-area">
1397 <div class='right'>
1398 <?php if (metaslider_viewing_trashed_slides($this->slider->id)) {
1399
1400 // Show a notice explaining the trash?>
1401 <div class="ms-postbox trashed-notice">
1402 <div class="notice-info"><?php printf(__('You are viewing slides that have been trashed, which will be automatically deleted in %s days. Click <a href="%s">here</a> to view active slides.', 'ml-slider'), EMPTY_TRASH_DAYS, admin_url("?page=metaslider&id={$this->slider->id}")); ?></div>
1403
1404 <?php
1405 // TODO this is a temp fix to avoid a compatability check in pro
1406 echo "<input type='checkbox' style='display:none;' checked class='select-slider' rel='flex'></inpu>";
1407 ?>
1408 </div>
1409 <?php } else {?>
1410 <div class="ms-postbox" id="metaslider_configuration">
1411 <div class='configuration metaslider-actions'>
1412 <metaslider-preview
1413 slideshow-id="<?php echo $this->slider->id; ?>"
1414 :keyboard-control="[18, 80]"
1415 ></metaslider-preview>
1416 <button class='alignright button button-primary' type='submit' name='save' id='ms-save'>
1417 <?php _e("Save", "ml-slider"); ?>
1418 </button>
1419 <span class="spinner"></span>
1420 </div>
1421 <div class="inside wp-clearfix">
1422 <table class="settings">
1423 <tbody>
1424 <?php
1425 $aFields = array(
1426 'type' => array(
1427 'priority' => 0,
1428 'type' => 'slider-lib',
1429 'value' => $this->slider->get_setting('type'),
1430 'options' => array(
1431 'flex' => array('label' => "FlexSlider"),
1432 'responsive' => array('label' => "R. Slides"),
1433 'nivo' => array('label' => "Nivo Slider"),
1434 'coin' => array('label' => "Coin Slider")
1435 )
1436 ),
1437 'width' => array(
1438 'priority' => 10,
1439 'type' => 'number',
1440 'size' => 3,
1441 'min' => 0,
1442 'max' => 9999,
1443 'step' => 1,
1444 'value' => $this->slider->get_setting( 'width' ),
1445 'label' => __( "Width", "ml-slider" ),
1446 'class' => 'coin flex responsive nivo',
1447 'helptext' => __( "Slideshow width", "ml-slider" ),
1448 'after' => __( "px", "ml-slider" )
1449 ),
1450 'height' => array(
1451 'priority' => 20,
1452 'type' => 'number',
1453 'size' => 3,
1454 'min' => 0,
1455 'max' => 9999,
1456 'step' => 1,
1457 'value' => $this->slider->get_setting( 'height' ),
1458 'label' => __( "Height", "ml-slider" ),
1459 'class' => 'coin flex responsive nivo',
1460 'helptext' => __( "Slideshow height", "ml-slider" ),
1461 'after' => __( "px", "ml-slider" )
1462 ),
1463 'effect' => array(
1464 'priority' => 30,
1465 'type' => 'select',
1466 'value' => $this->slider->get_setting( 'effect' ),
1467 'label' => __( "Effect", "ml-slider" ),
1468 'class' => 'effect coin flex responsive nivo',
1469 'helptext' => __( "Slide transition effect", "ml-slider" ),
1470 'options' => array(
1471 'random' => array( 'class' => 'option coin nivo' , 'label' => __( "Random", "ml-slider" ) ),
1472 'swirl' => array( 'class' => 'option coin', 'label' => __( "Swirl", "ml-slider" ) ),
1473 'rain' => array( 'class' => 'option coin', 'label' => __( "Rain", "ml-slider" ) ),
1474 'straight' => array( 'class' => 'option coin', 'label' => __( "Straight", "ml-slider" ) ),
1475 'sliceDown' => array( 'class' => 'option nivo', 'label' => __( "Slide Down", "ml-slider" ) ),
1476 'sliceUp' => array( 'class' => 'option nivo', 'label' => __( "Slice Up", "ml-slider" ) ),
1477 'sliceUpLeft' => array( 'class' => 'option nivo', 'label' => __( "Slide Up Left", "ml-slider" ) ),
1478 'sliceUpDown' => array( 'class' => 'option nivo', 'label' => __( "Slice Up Down", "ml-slider" ) ),
1479 'slideUpDownLeft' => array( 'class' => 'option nivo', 'label' => __( "Slide Up Down Left", "ml-slider" ) ),
1480 'fold' => array( 'class' => 'option nivo', 'label' => __( "Fold", "ml-slider" ) ),
1481 'fade' => array( 'class' => 'option nivo flex responsive', 'label' => __( "Fade", "ml-slider" ) ),
1482 'slideInRight' => array( 'class' => 'option nivo', 'label' => __( "Slide In Right", "ml-slider" ) ),
1483 'slideInLeft' => array( 'class' => 'option nivo', 'label' => __( "Slide In Left", "ml-slider" ) ),
1484 'boxRandom' => array( 'class' => 'option nivo', 'label' => __( "Box Random", "ml-slider" ) ),
1485 'boxRain' => array( 'class' => 'option nivo', 'label' => __( "Box Rain", "ml-slider" ) ),
1486 'boxRainReverse' => array( 'class' => 'option nivo', 'label' => __( "Box Rain Reverse", "ml-slider" ) ),
1487 'boxRainGrowReverse' => array( 'class' => 'option nivo', 'label' => __( "Box Rain Grow Reverse", "ml-slider" ) ),
1488 'slide' => array( 'class' => 'option flex', 'label' => __( "Slide", "ml-slider" ) )
1489 ),
1490 ),
1491 'links' => array(
1492 'priority' => 50,
1493 'type' => 'checkbox',
1494 'label' => __( "Arrows", "ml-slider" ),
1495 'class' => 'option coin flex nivo responsive',
1496 'checked' => $this->slider->get_setting( 'links' ) == 'true' ? 'checked' : '',
1497 'helptext' => __( "Show the previous/next arrows", "ml-slider" )
1498 ),
1499 'navigation' => array(
1500 'priority' => 60,
1501 'type' => 'navigation',
1502 'label' => __("Navigation", "ml-slider"),
1503 'class' => 'option coin flex nivo responsive',
1504 'value' => $this->slider->get_setting('navigation'),
1505 'helptext' => __("Show the slide navigation bullets", "ml-slider"),
1506 'options' => array(
1507 'false' => array('label' => __("Hidden", "ml-slider")),
1508 'true' => array('label' => __("Dots", "ml-slider")),
1509 'thumbs' => array(
1510 'label' => __("Thumbnail", "ml-slider"),
1511 'addon_required' => true
1512 ),
1513 'filmstrip' => array(
1514 'label' => __("Filmstrip", "ml-slider"),
1515 'addon_required' => true
1516 ),
1517 )
1518 ),
1519 );
1520
1521 if ( $this->get_view() == 'dropdown' ) {
1522 $aFields['title'] = array(
1523 'type' => 'title',
1524 'priority' => 5,
1525 'class' => 'option flex nivo responsive coin',
1526 'value' => get_the_title($this->slider->id),
1527 'label' => __( "Title", "ml-slider" ),
1528 'helptext' => __( "Slideshow title", "ml-slider" )
1529 );
1530 }
1531
1532 $aFields = apply_filters( 'metaslider_basic_settings', $aFields, $this->slider );
1533
1534 echo $this->build_settings_rows( $aFields );
1535 ?>
1536 </tbody>
1537 </table>
1538
1539
1540 <?php
1541 // Show the restore button if there are trashed posts
1542 // Also, render but hide the link in case we want to show
1543 // it when the user deletes their first slide
1544 $count = count(metaslider_has_trashed_slides($this->slider->id));
1545 if (!metaslider_viewing_trashed_slides($this->slider->id)) { ?>
1546 <a <?php echo $count ? '' : "style='display:none;'" ?> class="restore-slide-link" title="<?php _e('View trashed slides', 'ml-slider'); ?>" href="<?php echo admin_url("?page=metaslider&id={$this->slider->id}&show_trashed=true"); ?>">
1547 <i><svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-trash-2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg></i><?php echo __('Trash', 'ml-slider'); if ($count) echo " <span>({$count})</span>";?>
1548 </a>
1549 <?php } ?>
1550 </div>
1551 </div><?php
1552 $theme = metaslider_themes::get_instance()->get_current_theme($this->slider->id);
1553 if (is_array($theme)) unset($theme['images']);
1554 $theme_error = is_wp_error($theme) ? $theme->get_error_message() : '';
1555 if (is_wp_error($theme)) $theme = false;
1556 ?>
1557 <metaslider-theme-viewer
1558 theme-directory-url="<?php echo METASLIDER_THEMES_URL; ?>"
1559 incoming-error-message="<?php echo $theme_error; ?>"
1560 v-bind:initial-theme='<?php echo json_encode($theme); ?>'>
1561 </metaslider-theme-viewer>
1562 <div class="ms-postbox">
1563 <?php echo $this->shortcode_tip(); ?>
1564 </div>
1565 <div class="ms-postbox ms-toggle closed" id="metaslider_advanced_settings">
1566 <div class="handlediv" title="<?php esc_attr_e('Click to toggle', 'ml-slider'); ?>"></div><h3 class="hndle"><span><?php _e("Advanced Settings", "ml-slider") ?></span></h3>
1567 <div class="inside">
1568 <table>
1569 <tbody>
1570 <?php
1571 $aFields = array(
1572 'fullWidth' => array(
1573 'priority' => 5,
1574 'type' => 'checkbox',
1575 'label' => __( "Stretch", "ml-slider" ),
1576 'class' => 'option flex nivo responsive',
1577 'after' => __( "100% wide output", "ml-slider" ),
1578 'checked' => $this->slider->get_setting( 'fullWidth' ) == 'true' ? 'checked' : '',
1579 'helptext' => __( "Stretch the slideshow output to fill it's parent container", "ml-slider" )
1580 ),
1581 'center' => array(
1582 'priority' => 10,
1583 'type' => 'checkbox',
1584 'label' => __( "Center align", "ml-slider" ),
1585 'class' => 'option coin flex nivo responsive',
1586 'checked' => $this->slider->get_setting( 'center' ) == 'true' ? 'checked' : '',
1587 'helptext' => __( "Center align the slideshow", "ml-slider" )
1588 ),
1589 'autoPlay' => array(
1590 'priority' => 20,
1591 'type' => 'checkbox',
1592 'label' => __("Auto play", "ml-slider"),
1593 'class' => 'option flex nivo responsive coin',
1594 'checked' => 'true' == $this->slider->get_setting('autoPlay') ? 'checked' : '',
1595 'helptext' => __("Transition between slides automatically", "ml-slider")
1596 ),
1597 'smartCrop' => array(
1598 'priority' => 30,
1599 'type' => 'select',
1600 'label' => __( "Image Crop", "ml-slider" ),
1601 'class' => 'option coin flex nivo responsive',
1602 'value' => $this->slider->get_setting( 'smartCrop' ),
1603 'options' => array(
1604 'true' => array( 'label' => __( "Smart Crop", "ml-slider" ), 'class' => '' ),
1605 'false' => array( 'label' => __( "Standard", "ml-slider" ), 'class' => '' ),
1606 'disabled' => array( 'label' => __( "Disabled", "ml-slider" ), 'class' => '' ),
1607 'disabled_pad' => array( 'label' => __( "Disabled (Smart Pad)", "ml-slider" ), 'class' => 'option flex' ),
1608 ),
1609 'helptext' => __( "Smart Crop ensures your responsive slides are cropped to a ratio that results in a consistent slideshow size", "ml-slider" )
1610 ),
1611 'carouselMode' => array(
1612 'priority' => 40,
1613 'type' => 'checkbox',
1614 'label' => __( "Carousel mode", "ml-slider" ),
1615 'class' => 'option flex showNextWhenChecked',
1616 'checked' => $this->slider->get_setting( 'carouselMode' ) == 'true' ? 'checked' : '',
1617 'helptext' => __( "Display multiple slides at once. Slideshow output will be 100% wide.", "ml-slider" )
1618 ),
1619 'carouselMargin' => array(
1620 'priority' => 45,
1621 'min' => 0,
1622 'max' => 9999,
1623 'step' => 1,
1624 'type' => 'number',
1625 'label' => __( "Carousel margin", "ml-slider" ),
1626 'class' => 'option flex',
1627 'value' => $this->slider->get_setting( 'carouselMargin' ),
1628 'helptext' => __( "Pixel margin between slides in carousel.", "ml-slider" ),
1629 'after' => __( "px", "ml-slider" )
1630 ),
1631 'firstSlideFadeIn' => array(
1632 'priority' => 47,
1633 'type' => 'checkbox',
1634 'label' => __("Fade in", "ml-slider"),
1635 'class' => 'option flex',
1636 'checked' => 'true' == $this->slider->get_setting('firstSlideFadeIn') ? 'checked' : '',
1637 'helptext' => __("Fade in the first slide", "ml-slider"),
1638 ),
1639 'random' => array(
1640 'priority' => 50,
1641 'type' => 'checkbox',
1642 'label' => __( "Random", "ml-slider" ),
1643 'class' => 'option coin flex nivo responsive',
1644 'checked' => $this->slider->get_setting( 'random' ) == 'true' ? 'checked' : '',
1645 'helptext' => __( "Randomise the order of the slides", "ml-slider" )
1646 ),
1647 'hoverPause' => array(
1648 'priority' => 60,
1649 'type' => 'checkbox',
1650 'label' => __( "Hover pause", "ml-slider" ),
1651 'class' => 'option coin flex nivo responsive',
1652 'checked' => $this->slider->get_setting( 'hoverPause' ) == 'true' ? 'checked' : '',
1653 'helptext' => __( "Pause the slideshow when hovering over slider, then resume when no longer hovering.", "ml-slider" )
1654 ),
1655 'reverse' => array(
1656 'priority' => 70,
1657 'type' => 'checkbox',
1658 'label' => __( "Reverse", "ml-slider" ),
1659 'class' => 'option flex',
1660 'checked' => $this->slider->get_setting( 'reverse' ) == 'true' ? 'checked' : '',
1661 'helptext' => __( "Reverse the animation direction", "ml-slider" )
1662 ),
1663 'delay' => array(
1664 'priority' => 80,
1665 'type' => 'number',
1666 'size' => 3,
1667 'min' => 500,
1668 'max' => 10000,
1669 'step' => 100,
1670 'value' => $this->slider->get_setting( 'delay' ),
1671 'label' => __( "Slide delay", "ml-slider" ),
1672 'class' => 'option coin flex responsive nivo',
1673 'helptext' => __( "How long to display each slide, in milliseconds", "ml-slider" ),
1674 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1675 ),
1676 'animationSpeed' => array(
1677 'priority' => 90,
1678 'type' => 'number',
1679 'size' => 3,
1680 'min' => 0,
1681 'max' => 2000,
1682 'step' => 100,
1683 'value' => $this->slider->get_setting( 'animationSpeed' ),
1684 'label' => __( "Animation speed", "ml-slider" ),
1685 'class' => 'option flex responsive nivo',
1686 'helptext' => __( "Set the speed of animations, in milliseconds", "ml-slider" ),
1687 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1688 ),
1689 'slices' => array(
1690 'priority' => 100,
1691 'type' => 'number',
1692 'size' => 3,
1693 'min' => 0,
1694 'max' => 20,
1695 'step' => 1,
1696 'value' => $this->slider->get_setting( 'slices' ),
1697 'label' => __( "Number of slices", "ml-slider" ),
1698 'class' => 'option nivo',
1699 'helptext' => __( "Number of slices", "ml-slider" ),
1700 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1701 ),
1702 'spw' => array(
1703 'priority' => 110,
1704 'type' => 'number',
1705 'size' => 3,
1706 'min' => 0,
1707 'max' => 20,
1708 'step' => 1,
1709 'value' => $this->slider->get_setting( 'spw' ),
1710 'label' => __( "Number of squares", "ml-slider" ) . " (" . __( "Width", "ml-slider" ) . ")",
1711 'class' => 'option nivo',
1712 'helptext' => __( "Number of squares", "ml-slider" ),
1713 'after' => ''
1714 ),
1715 'sph' => array(
1716 'priority' => 120,
1717 'type' => 'number',
1718 'size' => 3,
1719 'min' => 0,
1720 'max' => 20,
1721 'step' => 1,
1722 'value' => $this->slider->get_setting( 'sph' ),
1723 'label' => __( "Number of squares", "ml-slider" ) . " (" . __( "Height", "ml-slider" ) . ")",
1724 'class' => 'option nivo',
1725 'helptext' => __( "Number of squares", "ml-slider" ),
1726 'after' => ''
1727 ),
1728 'direction' => array(
1729 'priority' => 130,
1730 'type' => 'select',
1731 'label' => __( "Slide direction", "ml-slider" ),
1732 'class' => 'option flex',
1733 'helptext' => __( "Select the sliding direction", "ml-slider" ),
1734 'value' => $this->slider->get_setting( 'direction' ),
1735 'options' => array(
1736 'horizontal' => array( 'label' => __( "Horizontal", "ml-slider" ), 'class' => '' ),
1737 'vertical' => array( 'label' => __( "Vertical", "ml-slider" ), 'class' => '' ),
1738 )
1739 ),
1740 'easing' => array(
1741 'priority' => 140,
1742 'type' => 'select',
1743 'label' => __( "Easing", "ml-slider" ),
1744 'class' => 'option flex',
1745 'helptext' => __( "Animation easing effect", "ml-slider" ),
1746 'value' => $this->slider->get_setting( 'easing' ),
1747 'options' => $this->get_easing_options()
1748 ),
1749 'prevText' => array(
1750 'priority' => 150,
1751 'type' => 'text',
1752 'label' => __( "Previous text", "ml-slider" ),
1753 'class' => 'option coin flex responsive nivo',
1754 'helptext' => __( "Set the text for the 'previous' direction item", "ml-slider" ),
1755 'value' => $this->slider->get_setting( 'prevText' ) == 'false' ? '' : $this->slider->get_setting( 'prevText' )
1756 ),
1757 'nextText' => array(
1758 'priority' => 160,
1759 'type' => 'text',
1760 'label' => __( "Next text", "ml-slider" ),
1761 'class' => 'option coin flex responsive nivo',
1762 'helptext' => __( "Set the text for the 'next' direction item", "ml-slider" ),
1763 'value' => $this->slider->get_setting( 'nextText' ) == 'false' ? '' : $this->slider->get_setting( 'nextText' )
1764 ),
1765 'sDelay' => array(
1766 'priority' => 170,
1767 'type' => 'number',
1768 'size' => 3,
1769 'min' => 0,
1770 'max' => 500,
1771 'step' => 10,
1772 'value' => $this->slider->get_setting( 'sDelay' ),
1773 'label' => __( "Square delay", "ml-slider" ),
1774 'class' => 'option coin',
1775 'helptext' => __( "Delay between squares in ms", "ml-slider" ),
1776 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1777 ),
1778 'opacity' => array(
1779 'priority' => 180,
1780 'type' => 'number',
1781 'size' => 3,
1782 'min' => 0,
1783 'max' => 1,
1784 'step' => 0.1,
1785 'value' => $this->slider->get_setting( 'opacity' ),
1786 'label' => __( "Opacity", "ml-slider" ),
1787 'class' => 'option coin',
1788 'helptext' => __( "Opacity of title and navigation", "ml-slider" ),
1789 'after' => ''
1790 ),
1791 'titleSpeed' => array(
1792 'priority' => 190,
1793 'type' => 'number',
1794 'size' => 3,
1795 'min' => 0,
1796 'max' => 10000,
1797 'step' => 100,
1798 'value' => $this->slider->get_setting( 'titleSpeed' ),
1799 'label' => __( "Caption speed", "ml-slider" ),
1800 'class' => 'option coin',
1801 'helptext' => __( "Set the fade in speed of the caption", "ml-slider" ),
1802 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1803 ),
1804 'developerOptions' => array(
1805 'priority' => 195,
1806 'type' => 'divider',
1807 'class' => 'option coin flex responsive nivo',
1808 'value' => __( "Developer options", "ml-slider" )
1809 ),
1810 'cssClass' => array(
1811 'priority' => 200,
1812 'type' => 'text',
1813 'label' => __( "CSS classes", "ml-slider" ),
1814 'class' => 'option coin flex responsive nivo',
1815 'helptext' => __( "Specify any custom CSS Classes you would like to be added to the slider wrapper", "ml-slider" ),
1816 'value' => $this->slider->get_setting( 'cssClass' ) == 'false' ? '' : $this->slider->get_setting( 'cssClass' )
1817 ),
1818 'printCss' => array(
1819 'priority' => 210,
1820 'type' => 'checkbox',
1821 'label' => __( "Print CSS", "ml-slider" ),
1822 'class' => 'option coin flex responsive nivo useWithCaution',
1823 'checked' => $this->slider->get_setting( 'printCss' ) == 'true' ? 'checked' : '',
1824 'helptext' => __( "Uncheck this is you would like to include your own CSS", "ml-slider" )
1825 ),
1826 'printJs' => array(
1827 'priority' => 220,
1828 'type' => 'checkbox',
1829 'label' => __( "Print JS", "ml-slider" ),
1830 'class' => 'option coin flex responsive nivo useWithCaution',
1831 'checked' => $this->slider->get_setting( 'printJs' ) == 'true' ? 'checked' : '',
1832 'helptext' => __( "Uncheck this is you would like to include your own Javascript", "ml-slider" )
1833 ),
1834 'noConflict' => array(
1835 'priority' => 230,
1836 'type' => 'checkbox',
1837 'label' => __( "No conflict mode", "ml-slider" ),
1838 'class' => 'option flex',
1839 'checked' => $this->slider->get_setting( 'noConflict' ) == 'true' ? 'checked' : '',
1840 'helptext' => __( "Delay adding the flexslider class to the slideshow", "ml-slider" )
1841 ),
1842 );
1843
1844 $aFields = apply_filters( 'metaslider_advanced_settings', $aFields, $this->slider );
1845
1846 echo $this->build_settings_rows( $aFields );
1847 ?>
1848 </tbody>
1849 </table>
1850 </div>
1851 </div>
1852
1853 <?php $url = wp_nonce_url(admin_url("admin-post.php?action=metaslider_delete_slider&amp;slider_id={$this->slider->id}"), "metaslider_delete_slider"); ?>
1854
1855 <a class='delete-slider alignright ml-has-icon ml-button ml-delete-button' href='<?php echo $url ?>'><i><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></i><span><?php _e( "Delete Slideshow", "ml-slider" ) ?></span></a>
1856 </div>
1857 <?php } ?>
1858 </div>
1859 </div>
1860 </div>
1861 </form>
1862 <metaslider-import-module></metaslider-import-module>
1863 </div>
1864 </metaslider>
1865 </div>
1866 <?php
1867 }
1868
1869 /**
1870 * Append the 'Add Slider' button to selected admin pages
1871 *
1872 * @param string $context HTML being passed to amend HTML button
1873 * @return string HTML button
1874 */
1875 public function insert_metaslider_button($context) {
1876
1877 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
1878
1879 if ( ! current_user_can( $capability ) ) {
1880 return $context;
1881 }
1882
1883 global $pagenow;
1884
1885 if ( in_array( $pagenow, array( 'post.php', 'page.php', 'post-new.php', 'post-edit.php' ) ) ) {
1886 $context .= '<a href="#TB_inline?&inlineId=choose-meta-slider" class="thickbox button" title="' .
1887 __( "Select slideshow to insert into post", "ml-slider" ) .
1888 '"><span class="wp-media-buttons-icon" style="background: url(' . METASLIDER_ASSETS_URL .
1889 '/metaslider/matchalabs.png); background-repeat: no-repeat; background-position: left bottom;"></span> ' .
1890 __( "Add slider", "ml-slider" ) . '</a>';
1891 }
1892
1893 return $context;
1894
1895 }
1896
1897
1898 /**
1899 * Append the 'Choose MetaSlider' thickbox content to the bottom of selected admin pages
1900 */
1901 public function admin_footer() {
1902
1903 global $pagenow;
1904
1905 // Only run in post/page creation and edit screens
1906 if ( in_array( $pagenow, array( 'post.php', 'page.php', 'post-new.php', 'post-edit.php' ) ) ) {
1907 $sliders = $this->all_meta_sliders( 'title' );
1908 ?>
1909
1910 <script>
1911 jQuery(document).ready(function() {
1912 jQuery('#insertMetaSlider').on('click', function() {
1913 var id = jQuery('#metaslider-select option:selected').val();
1914 window.send_to_editor('[metaslider id=' + id + ']');
1915 tb_remove();
1916 })
1917 });
1918 </script>
1919
1920 <div id="choose-meta-slider" style="display: none;">
1921 <div class="wrap">
1922 <?php
1923 if ( count( $sliders ) ) {
1924 echo "<h3 style='margin-bottom: 20px;'>" . _x("Insert MetaSlider", 'Keep the plugin name "MetaSlider" when possible', "ml-slider") . "</h3>";
1925 echo "<select id='metaslider-select'>";
1926 echo "<option disabled=disabled>" . __( "Choose slideshow", "ml-slider" ) . "</option>";
1927 foreach ( $sliders as $slider ) {
1928 echo "<option value='{$slider['id']}'>{$slider['title']}</option>";
1929
1930 }
1931 echo "</select>";
1932 echo "<button class='button primary' id='insertMetaSlider'>" . __( "Insert slideshow", "ml-slider" ) . "</button>";
1933 } else {
1934 _e( "No slideshows found", "ml-slider" );
1935 }
1936 ?>
1937 </div>
1938 </div>
1939
1940 <?php
1941 }
1942 }
1943
1944
1945 /**
1946 * Return the MetaSlider pro upgrade iFrame
1947 */
1948 public function upgrade_to_pro_tab_layer() {
1949 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
1950 return wp_iframe(array($this, 'upgrade_to_pro_iframe_layer'));
1951 }
1952 }
1953
1954 /**
1955 * Media Manager iframe HTML - vimeo
1956 */
1957 public function upgrade_to_pro_iframe_layer() {
1958 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1959 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-layer&amp;utm_campaign=pro';
1960 $this->upgrade_to_pro_iframe(
1961 array(
1962 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/layers.png' alt='' />",
1963 "<p>" . sprintf(_x("Ideal for easily creating eye-catching presentations and slideshows using stunning effects with %s 30 animation options %s and a beautiful, easy to use interface.", 'Translators: %s opens and closes a strong tag', 'ml-slider'), '<strong>', '</strong>') . " " . sprintf(_x('Layers can include %1$s text, HTML, images, videos %2$s and even %1$s shortcodes%2$s!', 'Translators: %1$s opens and %2$s closes a strong tag', 'ml-slider'), '<strong>', '</strong>') . "</p>",
1964 "<p>" . __("Additional optimization and customization options including using a video as the slide background, and adjusting the padding and background color of each layer.", 'ml-slider') . "</p>",
1965 "<a class='probutton button button-primary button-hero' href='{$link}' target='_blank'>" . __('Find out more about all the features of the Add-on Pack here', 'ml-slider') . "</a>",
1966 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
1967 )
1968 );
1969 }
1970
1971 /**
1972 * Return the MetaSlider pro upgrade iFrame for Vimeo
1973 */
1974 public function upgrade_to_pro_tab_vimeo() {
1975 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
1976 return wp_iframe(array($this, 'upgrade_to_pro_iframe_vimeo'));
1977 }
1978 }
1979
1980 /**
1981 * Media Manager iframe HTML - vimeo
1982 */
1983 public function upgrade_to_pro_iframe_vimeo() {
1984 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1985 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-vimeo&amp;utm_campaign=pro';
1986 $this->upgrade_to_pro_iframe(
1987 array(
1988 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/vimeo.png' alt='' />",
1989 "<h3>" . __('Create a slideshow full of your favorite videos easily and quickly by simply adding a URL to a Vimeo slide.', 'ml-slider') . "</h3>",
1990 "<p>" . __('Features include an automatic play/pause function, in which your slideshow will detect when you set a video to play and continue once the video has finished.', 'ml-slider') . "</p>",
1991 "<p>" . __('You could even have the slider autoplay a video, giving you a smooth, completely automatic presentation!', 'ml-slider') . "</p>",
1992 "<a class='probutton button button-primary button-hero' href='{$link}' target='_blank'>" . __('Find out more about all the features of the Add-on Pack here', 'ml-slider') . "</a>",
1993 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
1994 )
1995 );
1996 }
1997
1998 /**
1999 * Return the MetaSlider pro upgrade iFrame
2000 */
2001 public function upgrade_to_pro_tab_youtube() {
2002 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
2003 return wp_iframe(array($this, 'upgrade_to_pro_iframe_youtube'));
2004 }
2005 }
2006 /**
2007 * Media Manager iframe HTML - youtube
2008 */
2009 public function upgrade_to_pro_iframe_youtube() {
2010 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
2011 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-youtube&amp;utm_campaign=pro';
2012 $this->upgrade_to_pro_iframe(
2013 array(
2014 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/youtube.png' alt='' />",
2015 "<h3>" . __('Create a slideshow full of your favorite videos easily and quickly by simply adding a URL to a YouTube slide.', 'ml-slider') . "</h3>",
2016 "<p>" . __('Features include an automatic play/pause function, in which your slideshow will detect when you set a video to play and continue once the video has finished.', 'ml-slider') . "</p>",
2017 "<p>" . __('You could even have the slider autoplay a video, giving you a smooth, completely automatic presentation!', 'ml-slider') . "</p>",
2018 "<a class='probutton button button-primary button-hero' href='{$link}' target='_blank'>" . __('Find out more about all the features of the Add-on Pack here', 'ml-slider') . "</a>",
2019 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
2020 )
2021 );
2022 }
2023 /**
2024 * Return the MetaSlider pro upgrade iFrame
2025 */
2026 public function upgrade_to_pro_tab_post_feed() {
2027 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
2028 return wp_iframe(array($this, 'upgrade_to_pro_iframe_post_feed'));
2029 }
2030 }
2031 /**
2032 * Media Manager iframe HTML - post_feed
2033 */
2034 public function upgrade_to_pro_iframe_post_feed() {
2035 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
2036 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-feed&amp;utm_campaign=pro';
2037 $this->upgrade_to_pro_iframe(
2038 array(
2039 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/post-feed.png' alt='' />",
2040 "<p>" . sprintf(_x('Show off your %1$sblog posts%2$s, %1$sevents%2$s, %1$sWooCommerce products%2$s and other content with %1$sPost Feed%2$s.', 'Translators: %1$s opens and %2$s closes a strong tag', 'ml-slider'), '<strong>', '</strong>') . "</p>",
2041 "<p>" . __('Customise and control which post types you want to display, their order and how to restrict posts to certain tags or categories.', 'ml-slider') . "</p>",
2042 "<p>" . __('Post Feed slides can also be used with other slide types to either show one post at a time or in a carousel mode, allowing you to show off a large number of your latest posts in a small amount of space.', 'ml-slider') . "</p>",
2043 "<a class='probutton button button-primary button-hero' href='{$link}' target='_blank'>" . __('Find out more about all the features of the Add-on Pack here', 'ml-slider') . "</a>",
2044 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
2045 )
2046 );
2047 }
2048
2049 /**
2050 * Upgrade to pro Iframe - Render
2051 *
2052 * @param string $content The HTML to render
2053 */
2054 public function upgrade_to_pro_iframe($content) {
2055 wp_enqueue_style('metaslider-admin-styles', METASLIDER_ADMIN_URL . 'assets/css/admin.css', false, METASLIDER_VERSION);
2056 wp_enqueue_script('google-font-api', 'https://fonts.googleapis.com/css?family=PT+Sans:400,700' , false, METASLIDER_VERSION);
2057
2058 echo "<div class='metaslider_pro'>";
2059 echo implode("", $content);
2060 echo "</div>";
2061 }
2062
2063 /**
2064 * Provide a tip so the user can add the slideshow to thier site
2065 *
2066 * @return string the tip
2067 */
2068 public function shortcode_tip() {
2069 // Title
2070 return '<h3 class="hndle metaslider-shortcode-title"><span>' . __("How to Use", "ml-slider") . '</span>' .
2071
2072 // Switch to title button
2073 '<div class="ms-action-buttons wp-clearfix"><button data-type="id" id="ms-copy-type" class="ml-button ml-skinless-button tipsy-tooltip-top" title="' . __("Show title", "ml-slider") . '"><i><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-shuffle"><polyline points="16 3 21 3 21 8"></polyline><line x1="4" y1="20" x2="21" y2="3"></line><polyline points="21 16 21 21 16 21"></polyline><line x1="15" y1="15" x2="21" y2="21"></line><line x1="4" y1="4" x2="9" y2="9"></line></svg></i></button>' .
2074
2075 // Copy all button
2076 '<button id="ms-copy-all" class="ml-button ml-skinless-button tipsy-tooltip-top" title="' . __("Copy all code", "ml-slider") . '"><i><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-copy"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></i></button></div>' .
2077
2078 '</h3>' .
2079
2080 // Container
2081 '<div class="inside wp-clearfix metaslider-shortcode">' .
2082
2083 // Description
2084 '<p>' . __('To display your slideshow using id or title, add the following shortcodes (in orange) to your page. If adding the slideshow to your theme files, additionally include the surrounding PHP function (in gray).', 'ml-slider') . '</p>' .
2085
2086 // Shortcode
2087 '<pre class="ms-entire" id="ms-entire-code">&lt;?php echo do_shortcode(\'<br>&emsp;&emsp;<div class="ms-shortcode">[metaslider <span id="ms-shortcode-id">id="' . $this->slider->id . '"</span><span style="display:none" id="ms-shortcode-title">title="' . get_the_title($this->slider->id) . '"</span>]</div><br>\'); ?&gt;</pre>' .
2088
2089 '</div>';
2090 }
2091
2092 /**
2093 * Adds extra links to the plugin activation page
2094 *
2095 * @param array $meta Extra meta links
2096 * @param string $file Specific file to compare against the base plugin
2097 * @param string $data Data for the meat links
2098 * @param string $status Staus of the meta links
2099 * @return array Return the meta links array
2100 */
2101 public function get_extra_meta_links($meta, $file, $data, $status) {
2102
2103 if (plugin_basename(__FILE__) == $file) {
2104 $plugin_page = admin_url('admin.php?page=metaslider');
2105 $meta[] = "<a href='{$plugin_page}' onclick=\"event.preventDefault();var link = jQuery(this);jQuery.post(ajaxurl, {action: 'reset_tour_status', _wpnonce: metaslider_tour_nonce }, function(data) {window.location = link.attr('href');});\">" . __('Take a tour', 'ml-slider') . "</a>";
2106 if (metaslider_pro_is_installed()) {
2107 $meta[] = "<a href='https://www.metaslider.com/support/' target='_blank'>" . __('Premium Support', 'ml-slider') . "</a>";
2108 } else {
2109 $upgrade_link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
2110 $meta[] = "<a href='{$upgrade_link}' target='_blank'>" . __('Add-ons', 'ml-slider') . "</a>";
2111 $meta[] = "<a href='https://wordpress.org/support/plugin/ml-slider/' target='_blank'>" . __('Support', 'ml-slider') . "</a>";
2112 }
2113 $meta[] = "<a href='https://www.metaslider.com/documentation/' target='_blank'>" . __('Documentation', 'ml-slider') . "</a>";
2114 $meta[] = "<a href='https://wordpress.org/support/plugin/ml-slider/reviews#new-post' target='_blank' title='" . __('Leave a review', 'ml-slider') . "'><i class='ml-stars'><svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg><svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg><svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg><svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg><svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg></i></a>";
2115 }
2116 return $meta;
2117 }
2118
2119 /**
2120 * Adds styles to admin head to allow for stars animation and coloring
2121 */
2122 public function add_star_styles() {
2123 if (metaslider_user_is_on_admin_page('plugins.php')) {?>
2124 <style>
2125 .ml-stars{display:inline-block;color:#ffb900;position:relative;top:3px}
2126 .ml-stars svg{fill:#ffb900}
2127 .ml-stars svg:hover{fill:#ffb900}
2128 .ml-stars svg:hover ~ svg{fill:none}
2129 </style>
2130 <?php }
2131 }
2132
2133 /**
2134 * Add nonce to activation pa
2135 */
2136 public function add_tour_nonce_to_activation_page() {
2137 if (metaslider_user_is_on_admin_page('plugins.php')) {?>
2138 <script>
2139 var metaslider_tour_nonce = "<?php echo wp_create_nonce('metaslider_tour_nonce'); ?>";
2140 </script>
2141 <?php }
2142 }
2143
2144 /**
2145 * Upgrade To Pro Button.
2146 *
2147 * @return string Returns a HTMl button
2148 */
2149 public function upgrade_to_pro_top_button() {
2150 $text = __('Upgrade Now', "ml-slider");
2151 $link = metaslider_get_upgrade_link();
2152 $upgrade_text = __("Get The Pro Pack Today!", "ml-slider");
2153 return "<a target='_blank' title='{$upgrade_text}' class='ml-has-icon ml-hanging-button' href='{$link}'><i class='brand-color'><svg xmlns='http://www.w3.org/2000/svg' width='17' height='17' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg></i><span>{$text}</span></a>";
2154 }
2155
2156 /**
2157 * Toggle Layout Buttons.
2158 *
2159 * @return string returns html button
2160 */
2161 public function toggle_layout_button() {
2162
2163 // Don't show this if there are no slideshows
2164 if (!count($this->all_meta_sliders())) {
2165 return '';
2166 }
2167
2168 $view = ('tabs' == $this->get_view()) ? 'tabs' : 'dropdown';
2169 $view_opposite = ('dropdown' == $this->get_view()) ? 'tabs' : 'dropdown';
2170 $view_text = ($this->get_view() == 'tabs') ? __("Switch to Dropdown view", "ml-slider") : __("Switch to Tab view", "ml-slider");
2171 return "<a class='ml-has-icon ml-hanging-button' title='" . $view_text . "'
2172 href='" . admin_url( "admin-post.php?action=metaslider_switch_view&view=".$view_opposite) . "'><i><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"17\" height=\"17\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-shuffle\"><polyline points=\"16 3 21 3 21 8\"/><line x1=\"4\" y1=\"20\" x2=\"21\" y2=\"3\"/><polyline points=\"21 16 21 21 16 21\"/><line x1=\"15\" y1=\"15\" x2=\"21\" y2=\"21\"/><line x1=\"4\" y1=\"4\" x2=\"9\" y2=\"9\"/></svg></i><span>" . __("Layout", "ml-slider") . "</span></a>";
2173 }
2174
2175 /**
2176 * Link to the comparison page button
2177 *
2178 * @return string returns html button
2179 */
2180 public function addons_page_button() {
2181 $link = admin_url('admin.php?page=upgrade');
2182 return "<a class='ml-has-icon ml-hanging-button' title='" . __('View Add-ons / Other Plugins', 'ml-slider') . "' href='{$link}'><i><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"17\" height=\"17\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-clipboard\"><path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\"/><rect x=\"8\" y=\"2\" width=\"8\" height=\"4\" rx=\"1\" ry=\"1\"/></svg></i><span>" . __("Add-ons / Other Plugins", "ml-slider") . "</span></a>";
2183 }
2184
2185 /**
2186 * Support and Docs Button
2187 *
2188 * @return string returns html button
2189 */
2190 public function documentation_button() {
2191 return "<a class='ml-has-icon ml-hanging-button' target='_blank' title='" . __('View The Documentation', 'ml-slider') . "' href='https://www.metaslider.com/documentation/'><i><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"17\" height=\"17\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-book\"><path d=\"M4 19.5A2.5 2.5 0 0 1 6.5 17H20\"/><path d=\"M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z\"/></svg></i><span>" . __("Documentation", "ml-slider") . "</span></a>";
2192 }
2193
2194 /**
2195 * Add a 'property=stylesheet' attribute to the MetaSlider CSS links for HTML5 validation
2196 *
2197 * @since 3.3.4
2198 * @param string $tag Specifies tag
2199 * @param string $handle Checks for the handle to add property to
2200 * @return string
2201 */
2202 public function add_property_attribute_to_stylesheet_links( $tag, $handle ) {
2203
2204 if ( strpos( $handle, 'metaslider' ) !== FALSE && strpos( $tag, "property='" ) === FALSE ) {
2205 // we're only filtering tags with metaslider in the handle, and links which don't already have a property attribute
2206 $tag = str_replace( "/>", "property='stylesheet' />", $tag );
2207 }
2208
2209 return $tag;
2210
2211 }
2212
2213 }
2214
2215 endif;
2216
2217 add_action('plugins_loaded', array(MetaSliderPlugin::get_instance(), 'setup'), 10);
2218