PluginProbe ʕ •ᴥ•ʔ
Slider, Gallery, and Carousel by MetaSlider – Image Slider, Video Slider / 3.11.1
Slider, Gallery, and Carousel by MetaSlider – Image Slider, Video Slider v3.11.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
2059 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.11.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.11.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 $this->slideshows = MetaSlider_Slideshows::get_instance();
87
88 // Default to WP (4.4) REST API but backup with admin ajax
89 require_once(METASLIDER_PATH . 'admin/routes/api.php');
90 $this->api = MetaSlider_Api::get_instance();
91 $this->api->setup();
92 $this->api->register_admin_ajax_hooks();
93 if (class_exists('WP_REST_Controller')) new MetaSlider_REST_Controller();
94
95 if (function_exists('register_block_type')) {
96 $this->gutenberg = new MetaSlider_Gutenberg($this);
97 }
98 }
99
100 /**
101 * Define MetaSlider constants
102 */
103 private function define_constants() {
104 if (!defined('METASLIDER_VERSION')) {
105 define('METASLIDER_VERSION', $this->version);
106 define('METASLIDER_BASE_URL', trailingslashit(plugin_dir_url(metaslider_plugin_is_installed('ml-slider'))));
107 define('METASLIDER_ASSETS_URL', trailingslashit(METASLIDER_BASE_URL . 'assets'));
108 define('METASLIDER_ADMIN_URL', trailingslashit(METASLIDER_BASE_URL . 'admin'));
109
110 // Use the themes in the plugin dir if it's there (useful for developing)
111 if (file_exists(trailingslashit(WP_PLUGIN_DIR) . 'ml-slider-themes/manifest.php')) {
112 define('METASLIDER_THEMES_PATH', trailingslashit(WP_PLUGIN_DIR) . 'ml-slider-themes/');
113 define('METASLIDER_THEMES_URL', trailingslashit(plugins_url('ml-slider-themes/')));
114 } else {
115 define('METASLIDER_THEMES_PATH', trailingslashit(METASLIDER_PATH . 'themes/'));
116 define('METASLIDER_THEMES_URL', trailingslashit(METASLIDER_BASE_URL . 'themes/'));
117 }
118 }
119 }
120
121 /**
122 * All MetaSlider classes
123 */
124 private function plugin_classes() {
125 return array(
126 'metaslider' => METASLIDER_PATH . 'inc/slider/metaslider.class.php',
127 'metacoinslider' => METASLIDER_PATH . 'inc/slider/metaslider.coin.class.php',
128 'metaflexslider' => METASLIDER_PATH . 'inc/slider/metaslider.flex.class.php',
129 'metanivoslider' => METASLIDER_PATH . 'inc/slider/metaslider.nivo.class.php',
130 'metaresponsiveslider' => METASLIDER_PATH . 'inc/slider/metaslider.responsive.class.php',
131 'metaslide' => METASLIDER_PATH . 'inc/slide/metaslide.class.php',
132 'metaimageslide' => METASLIDER_PATH . 'inc/slide/metaslide.image.class.php',
133 'metasliderimagehelper' => METASLIDER_PATH . 'inc/metaslider.imagehelper.class.php',
134 'metaslidersystemcheck' => METASLIDER_PATH . 'inc/metaslider.systemcheck.class.php',
135 'metaslider_widget' => METASLIDER_PATH . 'inc/metaslider.widget.class.php',
136 'simple_html_dom' => METASLIDER_PATH . 'inc/simple_html_dom.php',
137 'metaslider_notices' => METASLIDER_PATH . 'admin/Notices.php',
138 'metaslider_admin_pages' => METASLIDER_PATH . 'admin/Pages.php',
139 'metaslider_slideshows' => METASLIDER_PATH . 'admin/Slideshows/Slideshows.php',
140 'metaslider_themes' => METASLIDER_PATH . 'admin/Slideshows/Themes.php',
141 'metaslider_tour' => METASLIDER_PATH . 'admin/Tour.php',
142 'metaslider_gutenberg' => METASLIDER_PATH . 'admin/Gutenberg.php'
143 );
144 }
145
146 /**
147 * Load required classes
148 */
149 private function includes() {
150 require_once(METASLIDER_PATH . 'admin/lib/helpers.php');
151 // require_once(METASLIDER_PATH . 'admin/lib/temporary.php');
152 $autoload_is_disabled = defined( 'METASLIDER_AUTOLOAD_CLASSES' ) && METASLIDER_AUTOLOAD_CLASSES === false;
153 if ( function_exists( "spl_autoload_register" ) && ! ( $autoload_is_disabled ) ) {
154
155 // >= PHP 5.2 - Use auto loading
156 if ( function_exists( "__autoload" ) ) {
157 spl_autoload_register( "__autoload" );
158 }
159
160 spl_autoload_register( array( $this, 'autoload' ) );
161
162 } else {
163
164 // < PHP5.2 - Require all classes
165 foreach ( $this->plugin_classes() as $id => $path ) {
166 if ( is_readable( $path ) && ! class_exists( $id ) ) {
167 require_once( $path );
168 }
169 }
170
171 }
172
173 }
174
175
176 /**
177 * Autoload MetaSlider classes to reduce memory consumption
178 *
179 * @param string $class Class name
180 */
181 public function autoload( $class ) {
182
183 $classes = $this->plugin_classes();
184
185 $class_name = strtolower( $class );
186
187 if ( isset( $classes[$class_name] ) && is_readable( $classes[$class_name] ) ) {
188 require_once( $classes[$class_name] );
189 }
190
191 }
192
193
194 /**
195 * Register the [metaslider] shortcode.
196 */
197 private function setup_shortcode() {
198
199 add_shortcode( 'metaslider', array( $this, 'register_shortcode' ) );
200 add_shortcode( 'ml-slider', array( $this, 'register_shortcode' ) ); // backwards compatibility
201
202 }
203
204
205 /**
206 * Hook MetaSlider into WordPress
207 */
208 private function setup_actions() {
209 add_action('admin_menu', array($this, 'register_admin_pages'), 9553);
210 add_action('init', array($this, 'register_post_types'));
211 add_action('init', array($this, 'register_taxonomy'));
212 add_action('init', array($this, 'load_plugin_textdomain'));
213 add_action('admin_footer', array($this, 'admin_footer'), 11);
214 add_action('widgets_init', array($this, 'register_metaslider_widget'));
215
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', '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 * Check our WordPress installation is compatible with MetaSlider
433 */
434 public function do_system_check() {
435
436 $systemCheck = new MetaSliderSystemCheck();
437 $systemCheck->check();
438
439 }
440
441
442 /**
443 * Update the tab options in the media manager
444 *
445 * @param array $strings Array of settings for custom media tabs
446 * @return array
447 */
448 public function custom_media_uploader_tabs( $strings ) {
449
450 // update strings
451 if ( ( isset( $_GET['page'] ) && $_GET['page'] == 'metaslider' ) ) {
452 $strings['insertMediaTitle'] = __( "Image", "ml-slider" );
453 $strings['insertIntoPost'] = __( "Add to slideshow", "ml-slider" );
454
455 // remove options
456 $strings_to_remove = array(
457 'createVideoPlaylistTitle',
458 'createGalleryTitle',
459 'insertFromUrlTitle',
460 'createPlaylistTitle'
461 );
462
463 foreach ($strings_to_remove as $string) {
464 if (isset($strings[$string])) {
465 unset($strings[$string]);
466 }
467 }
468 }
469
470 return $strings;
471
472 }
473
474
475 /**
476 * Add extra tabs to the default wordpress Media Manager iframe
477 *
478 * @param array $tabs existing media manager tabs]
479 * @return array
480 */
481 public function custom_media_upload_tab_name( $tabs ) {
482
483 $metaslider_tabs = array( 'post_feed', 'layer', 'youtube', 'vimeo' );
484
485 // restrict our tab changes to the MetaSlider plugin page
486 if ( ( isset( $_GET['page'] ) && $_GET['page'] == 'metaslider' ) || ( isset( $_GET['tab'] ) && in_array( $_GET['tab'], $metaslider_tabs ) ) ) {
487 $newtabs = array();
488
489 if ( function_exists( 'is_plugin_active' ) && ! is_plugin_active( 'ml-slider-pro/ml-slider-pro.php' ) ) {
490 $newtabs = array(
491 'post_feed' => __( "Post Feed", "metaslider" ),
492 'vimeo' => __( "Vimeo", "metaslider" ),
493 'youtube' => __( "YouTube", "metaslider" ),
494 'layer' => __( "Layer Slide", "metaslider" )
495 );
496 }
497
498 if ( isset( $tabs['nextgen'] ) )
499 unset( $tabs['nextgen'] );
500
501
502 if ( is_array( $tabs ) ) {
503 return array_merge( $tabs, $newtabs );
504 } else {
505 return $newtabs;
506 }
507
508 }
509
510 return $tabs;
511
512
513 }
514
515 /**
516 * Set the current slider
517 *
518 * @param int $id ID for slider
519 * @param array $shortcode_settings Settings for slider
520 */
521 public function set_slider( $id, $shortcode_settings = array() ) {
522
523 $type = 'flex';
524
525 if ( isset( $shortcode_settings['type'] ) ) {
526 $type = $shortcode_settings['type'];
527 } else if ( $settings = get_post_meta( $id, 'ml-slider_settings', true ) ) {
528 if ( is_array( $settings ) && isset( $settings['type'] ) ) {
529 $type = $settings['type'];
530 }
531 }
532
533 if ( ! in_array( $type, array( 'flex', 'coin', 'nivo', 'responsive' ) ) ) {
534 $type = 'flex';
535 }
536
537 $this->slider = $this->load_slider( $type, $id, $shortcode_settings );
538
539 }
540
541
542 /**
543 * Create a new slider based on the sliders type setting
544 *
545 * @param string $type Type of slide
546 * @param int $id ID of slide
547 * @param string $shortcode_settings Shortcode settings
548 * @return array
549 */
550 private function load_slider( $type, $id, $shortcode_settings ) {
551
552 switch ( $type ) {
553 case( 'coin' ):
554 return new MetaCoinSlider( $id, $shortcode_settings );
555 case( 'flex' ):
556 return new MetaFlexSlider( $id, $shortcode_settings );
557 case( 'nivo' ):
558 return new MetaNivoSlider( $id, $shortcode_settings );
559 case( 'responsive' ):
560 return new MetaResponsiveSlider( $id, $shortcode_settings );
561 default:
562 return new MetaFlexSlider( $id, $shortcode_settings );
563
564 }
565 }
566
567 /**
568 * Update the slider
569 *
570 * @return string a JSON string with success or failure (and errors)
571 */
572 public function update_slider() {
573
574 // Wordpress will just die() if this fails
575 check_admin_referer("metaslider_update_slider");
576
577 if (!current_user_can(apply_filters('metaslider_capability', 'edit_others_posts'))) {
578 return wp_send_json_error(array(
579 'message' => __('The security check failed. Please refresh the page and try again.', 'ml-slider')
580 ), 401);
581 }
582
583 $slider_id = absint($_POST['slider_id']);
584 if (!$slider_id) {
585 return wp_send_json_error(array(
586 'message' => __("The slideshow you're trying to update was not found.", 'ml-slider')
587 ), 401);
588 }
589
590 $errors = new WP_Error();
591
592 // update settings
593 if (isset($_POST['settings'])) {
594 $new_settings = $_POST['settings'];
595 $old_settings = get_post_meta($slider_id, 'ml-slider_settings', true);
596
597 // convert submitted checkbox values from 'on' or 'off' to boolean values
598 $checkboxes = apply_filters("metaslider_checkbox_settings", array('noConflict', 'fullWidth', 'hoverPause', 'links', 'reverse', 'random', 'printCss', 'printJs', 'smoothHeight', 'center', 'carouselMode', 'autoPlay', 'firstSlideFadeIn', 'responsive_thumbs'));
599
600 foreach ($checkboxes as $checkbox) {
601 $new_settings[$checkbox] = (isset($new_settings[$checkbox]) && 'on' == $new_settings[$checkbox]) ? 'true' : 'false';
602 }
603
604 $settings = array_merge((array) $old_settings, $new_settings);
605
606 // update the slider settings
607 // TODO this will return false if the data is unchanged, so we should consider checking the data prior to updating it.
608 $result = update_post_meta($slider_id, 'ml-slider_settings', $settings);
609 // if (!$result) $errors->add('update_failed', __('There was an error while updating the post meta. Most likely this means nothing has changed.', 'ml-slider'));
610 }
611
612 // update slideshow title
613 if (isset($_POST['title'])) {
614 $result = wp_update_post(array(
615 'ID' => $slider_id,
616 'post_title' => esc_html($_POST['title'])
617 ));
618 if (!$result) $errors->add('update_failed', __('There was an error while updating the title.', 'ml-slider'));
619 }
620
621 // update individual slides
622 // TODO Refactor this to return better error handling.
623 if (isset($_POST['attachment'])) {
624 foreach ($_POST['attachment'] as $slide_id => $fields) {
625 do_action("metaslider_save_{$fields['type']}_slide", $slide_id, $slider_id, $fields);
626 }
627 }
628
629 if (count($errors->get_error_messages())) {
630 return wp_send_json_error($errors, 409);
631 }
632
633 return wp_send_json_success(array(
634 'message' => __('The slideshow was successfully updated.', 'ml-slider'),
635 ), 200);
636 }
637
638 /**
639 * Delete a slide via ajax.
640 *
641 * @return string Returns the status of the request
642 */
643 public function ajax_undelete_slide() {
644 if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'metaslider_undelete_slide')) {
645 return wp_send_json_error(array(
646 'message' => __('The security check failed. Please refresh the page and try again.', 'ml-slider')
647 ), 401);
648 }
649
650 $result = $this->undelete_slide(absint($_POST['slide_id']), absint($_POST['slider_id']));
651
652 if (is_wp_error($result)) {
653 return wp_send_json_error(array(
654 'message' => $result->get_error_message()
655 ), 409);
656 }
657
658 return wp_send_json_success(array(
659 'message' => __('The slide was successfully restored', 'ml-slider'),
660 ), 200);
661 }
662
663 /**
664 * Undeletes a slide.
665 *
666 * @param int $slide_id The ID of the slide
667 * @param int $slider_id The ID of the slider (for legacy purposes)
668 * @return mixed
669 */
670 public function undelete_slide($slide_id, $slider_id) {
671 if ('ml-slide' === get_post_type($slide_id)) {
672 return wp_update_post(array(
673 'ID' => $slide_id,
674 'post_status' => 'publish'
675 ), new WP_Error('update_failed', __('The attempt to restore the slide failed.', 'ml-slider'), array('status' => 409)));
676 }
677
678 /*
679 * Legacy: This removes the relationship between the slider and slide
680 * This restores the relationship between a slide and slider.
681 * If using a newer version, this relationship is never lost on delete.
682 */
683
684 // Get the slider's term and apply it to the slide.
685 $term = get_term_by('name', $slider_id, 'ml-slider');
686 return wp_set_object_terms($slide_id, $term->term_id, 'ml-slider');
687 }
688
689 /**
690 * Delete a slide via ajax.
691 */
692 public function ajax_delete_slide() {
693 if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'metaslider_delete_slide')) {
694 return wp_send_json_error(array(
695 'message' => __('The security check failed. Please refresh the page and try again.', 'ml-slider')
696 ), 401);
697 }
698
699 $result = $this->delete_slide(absint($_POST['slide_id']), absint($_POST['slider_id']));
700
701 if (is_wp_error($result)) {
702 return wp_send_json_error(array(
703 'message' => $result->get_error_message()
704 ), 409);
705 }
706
707 return wp_send_json_success(array(
708 'message' => __('The slide was successfully trashed', 'ml-slider'),
709 ), 200);
710 }
711
712 /**
713 * Delete a slide by either trashing it or for
714 * legacy reasons removing the taxonomy relationship.
715 *
716 * @param int $slide_id The ID of the slide
717 * @param int $slider_id The ID of the slider
718 * @return mixed Will return the terms or WP_Error
719 */
720 public function delete_slide($slide_id, $slider_id) {
721 if ('ml-slide' === get_post_type($slide_id)) {
722 return wp_update_post(array(
723 'ID' => $slide_id,
724 'post_status' => 'trash'
725 ), new WP_Error('update_failed', 'The attempt to delete the slide failed.', array('status' => 409)));
726 }
727
728 /*
729 * Legacy: This removes the relationship between the slider and slide
730 * A slider with ID 216 might have a term_id of 7
731 * A slide with ID 217 could have a term_taxonomy_id of 7
732 * Multiple slides would have this term_taxonomy_id of 7
733 */
734
735 // This returns the term_taxonomy_id (7 from example)
736 $current_terms = wp_get_object_terms($slide_id, 'ml-slider', array('fields' => 'ids'));
737
738 // This returns the term object, named after the slider ID
739 // The $term->term_id would be 7 in the example above
740 // It also includes the count of slides attached to the slider
741 $term = get_term_by('name', $slider_id, 'ml-slider');
742
743 // I'm not sure why this is here. It seems this is only useful if
744 // a slide was attached to multiple sliders. A slide should only
745 // have one $current_terms (7 above)
746 $new_terms = array();
747 foreach ($current_terms as $current_term) {
748 if ($current_term != $term->term_id) {
749 $new_terms[] = absint($current_term);
750 }
751 }
752
753 // This only works becasue $new_terms is an empty array,
754 // which deletes the relationship. I'm leaving the loop above
755 // in case it's here for some legacy reason I'm unaware of.
756 return wp_set_object_terms($slide_id, $new_terms, 'ml-slider');
757 }
758
759
760 /**
761 * Delete a slider (send it to trash)
762 *
763 * @deprecated 3.11.0 use the API
764 *
765 * @return string - the json response from the API
766 */
767 public function delete_slider() {
768 return $this->api->delete_slideshow($_REQUEST);
769 }
770
771 /**
772 * Switch view
773 *
774 * @return null
775 */
776 public function switch_view() {
777 global $user_ID;
778
779 $view = $_GET['view'];
780
781 $allowed_views = array('tabs', 'dropdown');
782
783 if ( ! in_array( $view, $allowed_views ) ) {
784 return;
785 }
786
787 delete_user_meta( $user_ID, "metaslider_view" );
788
789 if ( $view == 'dropdown' ) {
790 add_user_meta( $user_ID, "metaslider_view", "dropdown");
791 }
792
793 wp_redirect( admin_url( "admin.php?page=metaslider" ) );
794
795 }
796
797
798 /**
799 * Create a new slider
800 */
801 public function create_slider() {
802
803 // check nonce
804 check_admin_referer( "metaslider_create_slider" );
805
806 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
807
808 if ( ! current_user_can( $capability ) ) {
809 return;
810 }
811
812 $defaults = array();
813
814 // if possible, take a copy of the last edited slider settings in place of default settings
815 if ( $last_modified = $this->find_slider( 'modified', 'DESC' ) ) {
816 $defaults = get_post_meta( $last_modified, 'ml-slider_settings', true );
817 }
818
819 // insert the post
820 $id = wp_insert_post( array(
821 'post_title' => __("New Slideshow", "ml-slider"),
822 'post_status' => 'publish',
823 'post_type' => 'ml-slider'
824 )
825 );
826
827 // use the default settings if we can't find anything more suitable.
828 if ( empty( $defaults ) ) {
829 $slider = new MetaSlider( $id, array() );
830 $defaults = $slider->get_default_parameters();
831 }
832
833 // insert the post meta
834 add_post_meta( $id, 'ml-slider_settings', $defaults, true );
835
836 // create the taxonomy term, the term is the ID of the slider itself
837 wp_insert_term( $id, 'ml-slider' );
838
839 wp_redirect( admin_url( "admin.php?page=metaslider&id={$id}" ) );
840
841 }
842
843
844
845 /**
846 * Find a single slider ID. For example, last edited, or first published.
847 *
848 * @param string $orderby field to order.
849 * @param string $order direction (ASC or DESC).
850 * @return int slider ID.
851 */
852 private function find_slider( $orderby, $order ) {
853
854 $args = array(
855 'force_no_custom_order' => true,
856 'post_type' => 'ml-slider',
857 'num_posts' => 1,
858 'post_status' => 'publish',
859 'suppress_filters' => 1, // wpml, ignore language filter
860 'orderby' => $orderby,
861 'order' => $order
862 );
863
864 $the_query = new WP_Query( $args );
865
866 while ( $the_query->have_posts() ) {
867 $the_query->the_post();
868 return $the_query->post->ID;
869 }
870
871 wp_reset_query();
872
873 return false;
874
875 }
876
877
878 /**
879 * Get sliders. Returns a nicely formatted array of currently
880 * published sliders.
881 *
882 * @param string $sort_key Specified sort key
883 * @return array all published sliders
884 */
885 public function all_meta_sliders( $sort_key = 'date' ) {
886
887 $sliders = array();
888
889 // list the tabs
890 $args = array(
891 'post_type' => 'ml-slider',
892 'post_status' => 'publish',
893 'orderby' => $sort_key,
894 'suppress_filters' => 1, // wpml, ignore language filter
895 'order' => 'ASC',
896 'posts_per_page' => -1
897 );
898
899 $args = apply_filters( 'metaslider_all_meta_sliders_args', $args );
900
901 // WP_Query causes issues with other plugins using admin_footer to insert scripts
902 // use get_posts instead
903 $all_sliders = get_posts( $args );
904
905 foreach( $all_sliders as $slideshow ) {
906
907 $active = $this->slider && ( $this->slider->id == $slideshow->ID ) ? true : false;
908
909 $sliders[] = array(
910 'active' => $active,
911 'title' => $slideshow->post_title,
912 'id' => $slideshow->ID
913 );
914
915 }
916
917 return $sliders;
918
919 }
920
921
922 /**
923 * Compare array values
924 *
925 * @param array $elem1 The first element to comapre
926 * @param array $elem2 The second element to comapr
927 * @return bool
928 */
929 private function compare_elems( $elem1, $elem2 ) {
930
931 return $elem1['priority'] > $elem2['priority'];
932
933 }
934
935
936 /**
937 * Building setting rows
938 *
939 * @param array $settings array of fields to render
940 * @return string
941 */
942 public function build_settings_rows($settings) {
943
944 // order the fields by priority
945 uasort($settings, array($this, "compare_elems"));
946 $output = "";
947
948 // loop through the array and build the settings HTML
949 foreach ($settings as $id => $row) {
950 $helptext = isset($row['helptext']) ? htmlentities2($row['helptext']) : '';
951
952 switch ($row['type']) {
953
954 // checkbox input type
955 case 'checkbox':
956 $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']} />";
957 if (isset($row['after'])) {
958 $output .= "<span class='after'>{$row['after']}</span>";
959 }
960 $output .= "</td></tr>";
961 break;
962
963 // navigation row
964 case 'navigation':
965 $navigation_row = "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><ul>";
966 foreach ($row['options'] as $option_name => $option_value) {
967 $tease = isset($option_value['addon_required']) ? 'disabled' : '';
968 if (true === $row['value'] && 'true' === $option_name) {
969 $checked = checked(true, true, false);
970 } else if (false === $row['value'] && 'false' === $option_name) {
971 $checked = checked(true, true, false);
972 } else {
973 $checked = checked($option_name, $row['value'], false);
974 }
975 $disabled = $option_name == 'thumbnails' ? 'disabled' : '';
976 $navigation_row .= "<li><label class='{$tease}'><input {$tease} type='radio' name='settings[{$id}]' value='{$option_name}' {$checked} {$disabled}/>{$option_value['label']}</label>";
977 if (isset($option_value['addon_required']) && $option_value['addon_required']) {
978 $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'));
979 }
980 $navigation_row .= "</li>";
981 }
982 $navigation_row .= "</ul></td></tr>";
983 $output .= apply_filters('metaslider_navigation_options', $navigation_row, $this->slider);
984 break;
985
986 // navigation row
987 case 'radio':
988 $navigation_row = "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><ul>";
989 foreach ($row['options'] as $option_name => $option_value) {
990 $checked = checked($option_name, $row['value'], false);
991 $class = isset($option_value['class']) ? $option_value['class'] : "";
992 $navigation_row .= "<li><label><input type='radio' name='settings[{$id}]' value='{$option_name}' {$checked} class='radio {$class}'/>{$option_value['label']}</label></li>";
993 }
994 $navigation_row .= "</ul></td></tr>";
995 $output .= apply_filters('metaslider_navigation_options', $navigation_row, $this->slider);
996 break;
997
998 // header/divider row
999 case 'divider':
1000 $output .= "<tr class='{$row['type']}'><td colspan='2' class='divider'><b>{$row['value']}</b></td></tr>";
1001 break;
1002
1003 // slideshow select row
1004 case 'slider-lib':
1005 $output .= "<tr class='{$row['type']}'><td colspan='2' class='slider-lib-row'>";
1006 foreach ($row['options'] as $option_name => $option_value) {
1007 $checked = checked($option_name, $row['value'], false);
1008 $output .= "<input class='select-slider' id='{$option_name}' rel='{$option_name}' type='radio' name='settings[type]' value='{$option_name}' {$checked} />
1009 <label tabindex='0' for='{$option_name}'>{$option_value['label']}</label>";
1010 }
1011 $output .= "</td></tr>";
1012 break;
1013
1014 // number input type
1015 case 'number':
1016 $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>";
1017 break;
1018
1019 // select drop down
1020 case 'select':
1021 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><select class='option {$row['class']} {$id}' name='settings[{$id}]'>";
1022 foreach ($row['options'] as $option_name => $option_value) {
1023 $selected = selected($option_name, $row['value'], false);
1024 $output .= "<option class='{$option_value['class']}' value='{$option_name}' {$selected}>{$option_value['label']}</option>";
1025 }
1026 $output .= "</select></td></tr>";
1027 break;
1028
1029 // theme drop down
1030 case 'theme':
1031 $output .= "<tr class='{$row['type']}'><td class='tipsy-tooltip' title='{$helptext}'>{$row['label']}</td><td><select class='option {$row['class']} {$id}' name='settings[{$id}]'>";
1032 $themes = "";
1033 foreach ($row['options'] as $option_name => $option_value) {
1034 $selected = selected($option_name, $row['value'], false);
1035 $themes .= "<option class='{$option_value['class']}' value='{$option_name}' {$selected}>{$option_value['label']}</option>";
1036 }
1037 $output .= apply_filters('metaslider_get_available_themes', $themes, $this->slider->get_setting('theme'));
1038 $output .= "</select></td></tr>";
1039 break;
1040
1041 // text input type
1042 case 'text':
1043 $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>";
1044 break;
1045
1046 // text input type
1047 case 'textarea':
1048 $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>";
1049 break;
1050
1051 // text input type
1052 case 'title':
1053 $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>";
1054 break;
1055 }
1056 }
1057 return $output;
1058 }
1059
1060
1061 /**
1062 * Return an indexed array of all easing options
1063 *
1064 * @return array
1065 */
1066 private function get_easing_options() {
1067
1068 $options = array(
1069 'linear', 'swing', 'jswing', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad',
1070 'easeInCubic', 'easeOutCubic', 'easeInOutCubic', 'easeInQuart',
1071 'easeOutQuart', 'easeInOutQuart', 'easeInQuint', 'easeOutQuint',
1072 'easeInOutQuint', 'easeInSine', 'easeOutSine', 'easeInOutSine',
1073 'easeInExpo', 'easeOutExpo', 'easeInOutExpo', 'easeInCirc', 'easeOutCirc',
1074 'easeInOutCirc', 'easeInElastic', 'easeOutElastic', 'easeInOutElastic',
1075 'easeInBack', 'easeOutBack', 'easeInOutBack', 'easeInBounce', 'easeOutBounce',
1076 'easeInOutBounce'
1077 );
1078 $output = array();
1079
1080 foreach ( $options as $option) {
1081 $output[$option] = array(
1082 'label' => ucfirst( preg_replace( '/(\w+)([A-Z])/U', '\\1 \\2', $option)),
1083 'class' => ''
1084 );
1085 }
1086
1087 return $output;
1088
1089 }
1090
1091 /**
1092 * Output the slideshow selector.
1093 *
1094 * Show tabs or a dropdown list depending on the users saved preference.
1095 */
1096 public function print_slideshow_selector() {
1097 global $user_ID;
1098
1099 // First check if we have any slideshows yet
1100 if ($tabs = $this->all_meta_sliders()) {
1101
1102 // Next check if they have the tabs view selected
1103 if ('tabs' == $this->get_view()) {
1104
1105 // Render the tabs
1106 echo "<div class='nav-tab-wrapper'>";
1107 echo "<div class='nav-tabs'>";
1108 foreach ($tabs as $tab) {
1109 if (!isset($tab['title'])) continue;
1110 $active = isset($tab['active']) && filter_var($tab['active'], FILTER_VALIDATE_BOOLEAN);
1111 $title = esc_attr($tab['title']);
1112 $title_with_html_allowed = esc_html($tab['title']);
1113 if ($active) {
1114 echo "<div class='nav-tab nav-tab-active'><input class='no_last_pass' type='text' name='title' value='{$title}'></div>";
1115 } else {
1116 echo "<a href='?page=metaslider&amp;id={$tab['id']}' title= '{$title}' class='nav-tab'>{$title_with_html_allowed}</a>";
1117 }
1118 }
1119 echo "</div>";
1120
1121 // TODO: Update this button and the entire nav system to a vuejs component
1122 if ($button = $this->toggle_layout_button()) echo $button;
1123 echo "</div>";
1124
1125 // This will render the select dropdown view
1126 // TODO make this resemble the WP Nav menu UI perhaps
1127 } else {
1128 echo "<div class='manage-menus'>";
1129 echo "<label for='select-slideshow' class='selected-menu'>" . __("Select Slideshow", "ml-slider") . ": </label>";
1130 echo "<select name='select-slideshow' onchange='if (this.value) window.location.href=this.value'>";
1131
1132 $tabs = $this->all_meta_sliders('title');
1133 foreach ($tabs as $tab) {
1134 if (!isset($tab['title'])) continue;
1135 $active = isset($tab['active']) && filter_var($tab['active'], FILTER_VALIDATE_BOOLEAN);
1136 $selected = $active ? " selected" : "";
1137 $title = esc_attr($tab['title']);
1138 echo "<option value='?page=metaslider&amp;id={$tab['id']}'{$selected}>{$title}</option>";
1139 }
1140 echo "</select>";
1141
1142 // TODO: Update this button and the entire nav system to a vuejs component
1143 if ($button = $this->toggle_layout_button()) echo $button;
1144 echo "</div>";
1145 }
1146
1147 // This section is shown when there are no slideshows
1148 } else {
1149 include METASLIDER_PATH."admin/views/pages/start.php";
1150 }
1151 }
1152
1153 /**
1154 * Return the users saved view preference.
1155 */
1156 public function get_view() {
1157 global $user_ID;
1158
1159 if ( get_user_meta( $user_ID, "metaslider_view", true ) ) {
1160 return get_user_meta( $user_ID, "metaslider_view", true );
1161 }
1162
1163 return 'tabs';
1164 }
1165
1166
1167 /**
1168 * Render the admin page (tabs, slides, settings)
1169 */
1170 public function render_admin_page() {
1171
1172 // Default to the most recently modified slider
1173 $slider_id = $this->find_slider('modified', 'DESC');
1174
1175 // If the id parameter exists, verify and use that.
1176 if (isset($_REQUEST['id']) && $id = $_REQUEST['id']) {
1177 if (in_array(get_post_status(absint($id)), array('publish', 'inherit'))) {
1178 $slider_id = (int)$id;
1179 }
1180 }
1181
1182 // "Set the slider"
1183 // TODO figure out what this does and if it can be better stated
1184 // Perhaps maybe "apply_settings()" or something.
1185 if ($slider_id) {
1186 $this->set_slider($slider_id);
1187 }
1188
1189 $this->do_system_check();
1190
1191 $slider_id = $this->slider ? $this->slider->id : 0;
1192
1193 ?>
1194
1195 <script>
1196 var metaslider_slider_id = <?php echo $slider_id; ?>;
1197 </script>
1198
1199 <div id="metaslider-ui" class="metaslider metaslider-ui">
1200 <?php $slider_settings = get_post_meta($slider_id, 'ml-slider_settings', true); ?>
1201 <metaslider :id='<?php echo $slider_id; ?>' v-bind:settings='<?php echo json_encode($slider_settings);?>' inline-template>
1202 <div>
1203
1204 <?php include METASLIDER_PATH."admin/views/pages/parts/header.php"; ?>
1205
1206 <form accept-charset="UTF-8" action="<?php echo admin_url( 'admin-post.php'); ?>" method="post">
1207 <input type="hidden" name="action" value="metaslider_update_slider">
1208 <input type="hidden" name="slider_id" value="<?php echo $slider_id; ?>">
1209 <?php wp_nonce_field( 'metaslider_update_slider' ); ?>
1210
1211 <?php $this->print_slideshow_selector(); ?>
1212
1213 <?php // If there is no slideshow we don't need to show the rest
1214 if (!$this->slider) { echo '</form></div></metaslider>'; return false; } ?>
1215
1216 <div id='poststuff' class="metaslider-inner wp-clearfix">
1217 <div id='post-body' class='metabox-holder columns-2'>
1218
1219 <div id='post-body-content'>
1220 <div class="left">
1221
1222 <?php do_action( "metaslider_admin_table_before", $this->slider->id ); ?>
1223
1224 <table id="metaslider-slides-list" class="widefat sortable metaslider-slides-container">
1225 <thead>
1226 <tr>
1227 <?php if (metaslider_viewing_trashed_slides($this->slider->id)) {
1228
1229 // If they are on the trash page, show them?>
1230 <th class="trashed-header">
1231 <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>
1232 <small> <?php printf(__('<a href="%s">view active</a>', 'ml-slider'), admin_url("?page=metaslider&id={$this->slider->id}")); ?></small>
1233 </th>
1234 <?php } else { ?>
1235 <th class="slider-title" colspan="2">
1236 <h3 class="alignleft"><?php echo get_the_title($this->slider->id) ?></h3>
1237 <?php if (!metaslider_viewing_trashed_slides($this->slider->id)) {
1238
1239 // Remove the actions on trashed view?>
1240 <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" ) ?>'>
1241 <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>
1242 <span><?php _e("Add Slide", "ml-slider") ?></span>
1243 </button>
1244 <?php } ?>
1245 <?php do_action( "metaslider_admin_table_header_right", $this->slider->id ); ?>
1246 </th>
1247 <?php } ?>
1248 </tr>
1249 </thead>
1250
1251 <tbody>
1252 <?php
1253 $this->slider->render_admin_slides();
1254 ?>
1255 </tbody>
1256 </table>
1257
1258 <?php do_action( "metaslider_admin_table_after", $this->slider->id ); ?>
1259
1260 </div>
1261 </div>
1262
1263 <div id="postbox-container-1" class="postbox-container ml-sidebar metaslider-settings-area">
1264 <div class='right'>
1265 <?php if (metaslider_viewing_trashed_slides($this->slider->id)) {
1266
1267 // Show a notice explaining the trash?>
1268 <div class="ms-postbox trashed-notice">
1269 <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>
1270
1271 <?php
1272 // TODO this is a temp fix to avoid a compatability check in pro
1273 echo "<input type='checkbox' style='display:none;' checked class='select-slider' rel='flex'></inpu>";
1274 ?>
1275 </div>
1276 <?php } else {?>
1277 <div class="ms-postbox" id="metaslider_configuration">
1278 <div class='configuration metaslider-actions'>
1279 <metaslider-preview
1280 slideshow-id="<?php echo $this->slider->id; ?>"
1281 :keyboard-control="[18, 80]"
1282 ></metaslider-preview>
1283 <button class='alignright button button-primary' type='submit' name='save' id='ms-save'>
1284 <?php _e("Save", "ml-slider"); ?>
1285 </button>
1286 <span class="spinner"></span>
1287 </div>
1288 <div class="inside wp-clearfix">
1289 <table class="settings">
1290 <tbody>
1291 <?php
1292 $aFields = array(
1293 'type' => array(
1294 'priority' => 0,
1295 'type' => 'slider-lib',
1296 'value' => $this->slider->get_setting('type'),
1297 'options' => array(
1298 'flex' => array('label' => "FlexSlider"),
1299 'responsive' => array('label' => "R. Slides"),
1300 'nivo' => array('label' => "Nivo Slider"),
1301 'coin' => array('label' => "Coin Slider")
1302 )
1303 ),
1304 'width' => array(
1305 'priority' => 10,
1306 'type' => 'number',
1307 'size' => 3,
1308 'min' => 0,
1309 'max' => 9999,
1310 'step' => 1,
1311 'value' => $this->slider->get_setting( 'width' ),
1312 'label' => __( "Width", "ml-slider" ),
1313 'class' => 'coin flex responsive nivo',
1314 'helptext' => __( "Slideshow width", "ml-slider" ),
1315 'after' => __( "px", "ml-slider" )
1316 ),
1317 'height' => array(
1318 'priority' => 20,
1319 'type' => 'number',
1320 'size' => 3,
1321 'min' => 0,
1322 'max' => 9999,
1323 'step' => 1,
1324 'value' => $this->slider->get_setting( 'height' ),
1325 'label' => __( "Height", "ml-slider" ),
1326 'class' => 'coin flex responsive nivo',
1327 'helptext' => __( "Slideshow height", "ml-slider" ),
1328 'after' => __( "px", "ml-slider" )
1329 ),
1330 'effect' => array(
1331 'priority' => 30,
1332 'type' => 'select',
1333 'value' => $this->slider->get_setting( 'effect' ),
1334 'label' => __( "Effect", "ml-slider" ),
1335 'class' => 'effect coin flex responsive nivo',
1336 'helptext' => __( "Slide transition effect", "ml-slider" ),
1337 'options' => array(
1338 'random' => array( 'class' => 'option coin nivo' , 'label' => __( "Random", "ml-slider" ) ),
1339 'swirl' => array( 'class' => 'option coin', 'label' => __( "Swirl", "ml-slider" ) ),
1340 'rain' => array( 'class' => 'option coin', 'label' => __( "Rain", "ml-slider" ) ),
1341 'straight' => array( 'class' => 'option coin', 'label' => __( "Straight", "ml-slider" ) ),
1342 'sliceDown' => array( 'class' => 'option nivo', 'label' => __( "Slide Down", "ml-slider" ) ),
1343 'sliceUp' => array( 'class' => 'option nivo', 'label' => __( "Slice Up", "ml-slider" ) ),
1344 'sliceUpLeft' => array( 'class' => 'option nivo', 'label' => __( "Slide Up Left", "ml-slider" ) ),
1345 'sliceUpDown' => array( 'class' => 'option nivo', 'label' => __( "Slice Up Down", "ml-slider" ) ),
1346 'slideUpDownLeft' => array( 'class' => 'option nivo', 'label' => __( "Slide Up Down Left", "ml-slider" ) ),
1347 'fold' => array( 'class' => 'option nivo', 'label' => __( "Fold", "ml-slider" ) ),
1348 'fade' => array( 'class' => 'option nivo flex responsive', 'label' => __( "Fade", "ml-slider" ) ),
1349 'slideInRight' => array( 'class' => 'option nivo', 'label' => __( "Slide In Right", "ml-slider" ) ),
1350 'slideInLeft' => array( 'class' => 'option nivo', 'label' => __( "Slide In Left", "ml-slider" ) ),
1351 'boxRandom' => array( 'class' => 'option nivo', 'label' => __( "Box Random", "ml-slider" ) ),
1352 'boxRain' => array( 'class' => 'option nivo', 'label' => __( "Box Rain", "ml-slider" ) ),
1353 'boxRainReverse' => array( 'class' => 'option nivo', 'label' => __( "Box Rain Reverse", "ml-slider" ) ),
1354 'boxRainGrowReverse' => array( 'class' => 'option nivo', 'label' => __( "Box Rain Grow Reverse", "ml-slider" ) ),
1355 'slide' => array( 'class' => 'option flex', 'label' => __( "Slide", "ml-slider" ) )
1356 ),
1357 ),
1358 'links' => array(
1359 'priority' => 50,
1360 'type' => 'checkbox',
1361 'label' => __( "Arrows", "ml-slider" ),
1362 'class' => 'option coin flex nivo responsive',
1363 'checked' => $this->slider->get_setting( 'links' ) == 'true' ? 'checked' : '',
1364 'helptext' => __( "Show the previous/next arrows", "ml-slider" )
1365 ),
1366 'navigation' => array(
1367 'priority' => 60,
1368 'type' => 'navigation',
1369 'label' => __("Navigation", "ml-slider"),
1370 'class' => 'option coin flex nivo responsive',
1371 'value' => $this->slider->get_setting('navigation'),
1372 'helptext' => __("Show the slide navigation bullets", "ml-slider"),
1373 'options' => array(
1374 'false' => array('label' => __("Hidden", "ml-slider")),
1375 'true' => array('label' => __("Dots", "ml-slider")),
1376 'thumbs' => array(
1377 'label' => __("Thumbnail", "ml-slider"),
1378 'addon_required' => true
1379 ),
1380 'filmstrip' => array(
1381 'label' => __("Filmstrip", "ml-slider"),
1382 'addon_required' => true
1383 ),
1384 )
1385 ),
1386 );
1387
1388 if ( $this->get_view() == 'dropdown' ) {
1389 $aFields['title'] = array(
1390 'type' => 'title',
1391 'priority' => 5,
1392 'class' => 'option flex nivo responsive coin',
1393 'value' => get_the_title($this->slider->id),
1394 'label' => __( "Title", "ml-slider" ),
1395 'helptext' => __( "Slideshow title", "ml-slider" )
1396 );
1397 }
1398
1399 $aFields = apply_filters( 'metaslider_basic_settings', $aFields, $this->slider );
1400
1401 echo $this->build_settings_rows( $aFields );
1402 ?>
1403 </tbody>
1404 </table>
1405
1406
1407 <?php
1408 // Show the restore button if there are trashed posts
1409 // Also, render but hide the link in case we want to show
1410 // it when the user deletes their first slide
1411 $count = count(metaslider_has_trashed_slides($this->slider->id));
1412 if (!metaslider_viewing_trashed_slides($this->slider->id)) { ?>
1413 <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"); ?>">
1414 <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>";?>
1415 </a>
1416 <?php } ?>
1417 </div>
1418 </div><?php
1419 $theme = metaslider_themes::get_instance()->get_current_theme($this->slider->id);
1420 if (is_array($theme)) unset($theme['images']);
1421 $theme_error = is_wp_error($theme) ? $theme->get_error_message() : '';
1422 if (is_wp_error($theme)) $theme = false;
1423 ?>
1424 <metaslider-theme-viewer
1425 theme-directory-url="<?php echo METASLIDER_THEMES_URL; ?>"
1426 incoming-error-message="<?php echo $theme_error; ?>"
1427 v-bind:initial-theme='<?php echo json_encode($theme); ?>'>
1428 </metaslider-theme-viewer>
1429 <div class="ms-postbox">
1430 <?php echo $this->shortcode_tip(); ?>
1431 </div>
1432 <div class="ms-postbox ms-toggle closed" id="metaslider_advanced_settings">
1433 <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>
1434 <div class="inside">
1435 <table>
1436 <tbody>
1437 <?php
1438 $aFields = array(
1439 'fullWidth' => array(
1440 'priority' => 5,
1441 'type' => 'checkbox',
1442 'label' => __( "Stretch", "ml-slider" ),
1443 'class' => 'option flex nivo responsive',
1444 'after' => __( "100% wide output", "ml-slider" ),
1445 'checked' => $this->slider->get_setting( 'fullWidth' ) == 'true' ? 'checked' : '',
1446 'helptext' => __( "Stretch the slideshow output to fill it's parent container", "ml-slider" )
1447 ),
1448 'center' => array(
1449 'priority' => 10,
1450 'type' => 'checkbox',
1451 'label' => __( "Center align", "ml-slider" ),
1452 'class' => 'option coin flex nivo responsive',
1453 'checked' => $this->slider->get_setting( 'center' ) == 'true' ? 'checked' : '',
1454 'helptext' => __( "Center align the slideshow", "ml-slider" )
1455 ),
1456 'autoPlay' => array(
1457 'priority' => 20,
1458 'type' => 'checkbox',
1459 'label' => __("Auto play", "ml-slider"),
1460 'class' => 'option flex nivo responsive coin',
1461 'checked' => 'true' == $this->slider->get_setting('autoPlay') ? 'checked' : '',
1462 'helptext' => __("Transition between slides automatically", "ml-slider")
1463 ),
1464 'smartCrop' => array(
1465 'priority' => 30,
1466 'type' => 'select',
1467 'label' => __( "Image Crop", "ml-slider" ),
1468 'class' => 'option coin flex nivo responsive',
1469 'value' => $this->slider->get_setting( 'smartCrop' ),
1470 'options' => array(
1471 'true' => array( 'label' => __( "Smart Crop", "ml-slider" ), 'class' => '' ),
1472 'false' => array( 'label' => __( "Standard", "ml-slider" ), 'class' => '' ),
1473 'disabled' => array( 'label' => __( "Disabled", "ml-slider" ), 'class' => '' ),
1474 'disabled_pad' => array( 'label' => __( "Disabled (Smart Pad)", "ml-slider" ), 'class' => 'option flex' ),
1475 ),
1476 'helptext' => __( "Smart Crop ensures your responsive slides are cropped to a ratio that results in a consistent slideshow size", "ml-slider" )
1477 ),
1478 'carouselMode' => array(
1479 'priority' => 40,
1480 'type' => 'checkbox',
1481 'label' => __( "Carousel mode", "ml-slider" ),
1482 'class' => 'option flex showNextWhenChecked',
1483 'checked' => $this->slider->get_setting( 'carouselMode' ) == 'true' ? 'checked' : '',
1484 'helptext' => __( "Display multiple slides at once. Slideshow output will be 100% wide.", "ml-slider" )
1485 ),
1486 'carouselMargin' => array(
1487 'priority' => 45,
1488 'min' => 0,
1489 'max' => 9999,
1490 'step' => 1,
1491 'type' => 'number',
1492 'label' => __( "Carousel margin", "ml-slider" ),
1493 'class' => 'option flex',
1494 'value' => $this->slider->get_setting( 'carouselMargin' ),
1495 'helptext' => __( "Pixel margin between slides in carousel.", "ml-slider" ),
1496 'after' => __( "px", "ml-slider" )
1497 ),
1498 'firstSlideFadeIn' => array(
1499 'priority' => 47,
1500 'type' => 'checkbox',
1501 'label' => __("Fade in", "ml-slider"),
1502 'class' => 'option flex',
1503 'checked' => 'true' == $this->slider->get_setting('firstSlideFadeIn') ? 'checked' : '',
1504 'helptext' => __("Fade in the first slide", "ml-slider"),
1505 ),
1506 'random' => array(
1507 'priority' => 50,
1508 'type' => 'checkbox',
1509 'label' => __( "Random", "ml-slider" ),
1510 'class' => 'option coin flex nivo responsive',
1511 'checked' => $this->slider->get_setting( 'random' ) == 'true' ? 'checked' : '',
1512 'helptext' => __( "Randomise the order of the slides", "ml-slider" )
1513 ),
1514 'hoverPause' => array(
1515 'priority' => 60,
1516 'type' => 'checkbox',
1517 'label' => __( "Hover pause", "ml-slider" ),
1518 'class' => 'option coin flex nivo responsive',
1519 'checked' => $this->slider->get_setting( 'hoverPause' ) == 'true' ? 'checked' : '',
1520 'helptext' => __( "Pause the slideshow when hovering over slider, then resume when no longer hovering.", "ml-slider" )
1521 ),
1522 'reverse' => array(
1523 'priority' => 70,
1524 'type' => 'checkbox',
1525 'label' => __( "Reverse", "ml-slider" ),
1526 'class' => 'option flex',
1527 'checked' => $this->slider->get_setting( 'reverse' ) == 'true' ? 'checked' : '',
1528 'helptext' => __( "Reverse the animation direction", "ml-slider" )
1529 ),
1530 'delay' => array(
1531 'priority' => 80,
1532 'type' => 'number',
1533 'size' => 3,
1534 'min' => 500,
1535 'max' => 10000,
1536 'step' => 100,
1537 'value' => $this->slider->get_setting( 'delay' ),
1538 'label' => __( "Slide delay", "ml-slider" ),
1539 'class' => 'option coin flex responsive nivo',
1540 'helptext' => __( "How long to display each slide, in milliseconds", "ml-slider" ),
1541 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1542 ),
1543 'animationSpeed' => array(
1544 'priority' => 90,
1545 'type' => 'number',
1546 'size' => 3,
1547 'min' => 0,
1548 'max' => 2000,
1549 'step' => 100,
1550 'value' => $this->slider->get_setting( 'animationSpeed' ),
1551 'label' => __( "Animation speed", "ml-slider" ),
1552 'class' => 'option flex responsive nivo',
1553 'helptext' => __( "Set the speed of animations, in milliseconds", "ml-slider" ),
1554 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1555 ),
1556 'slices' => array(
1557 'priority' => 100,
1558 'type' => 'number',
1559 'size' => 3,
1560 'min' => 0,
1561 'max' => 20,
1562 'step' => 1,
1563 'value' => $this->slider->get_setting( 'slices' ),
1564 'label' => __( "Number of slices", "ml-slider" ),
1565 'class' => 'option nivo',
1566 'helptext' => __( "Number of slices", "ml-slider" ),
1567 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1568 ),
1569 'spw' => array(
1570 'priority' => 110,
1571 'type' => 'number',
1572 'size' => 3,
1573 'min' => 0,
1574 'max' => 20,
1575 'step' => 1,
1576 'value' => $this->slider->get_setting( 'spw' ),
1577 'label' => __( "Number of squares", "ml-slider" ) . " (" . __( "Width", "ml-slider" ) . ")",
1578 'class' => 'option nivo',
1579 'helptext' => __( "Number of squares", "ml-slider" ),
1580 'after' => ''
1581 ),
1582 'sph' => array(
1583 'priority' => 120,
1584 'type' => 'number',
1585 'size' => 3,
1586 'min' => 0,
1587 'max' => 20,
1588 'step' => 1,
1589 'value' => $this->slider->get_setting( 'sph' ),
1590 'label' => __( "Number of squares", "ml-slider" ) . " (" . __( "Height", "ml-slider" ) . ")",
1591 'class' => 'option nivo',
1592 'helptext' => __( "Number of squares", "ml-slider" ),
1593 'after' => ''
1594 ),
1595 'direction' => array(
1596 'priority' => 130,
1597 'type' => 'select',
1598 'label' => __( "Slide direction", "ml-slider" ),
1599 'class' => 'option flex',
1600 'helptext' => __( "Select the sliding direction", "ml-slider" ),
1601 'value' => $this->slider->get_setting( 'direction' ),
1602 'options' => array(
1603 'horizontal' => array( 'label' => __( "Horizontal", "ml-slider" ), 'class' => '' ),
1604 'vertical' => array( 'label' => __( "Vertical", "ml-slider" ), 'class' => '' ),
1605 )
1606 ),
1607 'easing' => array(
1608 'priority' => 140,
1609 'type' => 'select',
1610 'label' => __( "Easing", "ml-slider" ),
1611 'class' => 'option flex',
1612 'helptext' => __( "Animation easing effect", "ml-slider" ),
1613 'value' => $this->slider->get_setting( 'easing' ),
1614 'options' => $this->get_easing_options()
1615 ),
1616 'prevText' => array(
1617 'priority' => 150,
1618 'type' => 'text',
1619 'label' => __( "Previous text", "ml-slider" ),
1620 'class' => 'option coin flex responsive nivo',
1621 'helptext' => __( "Set the text for the 'previous' direction item", "ml-slider" ),
1622 'value' => $this->slider->get_setting( 'prevText' ) == 'false' ? '' : $this->slider->get_setting( 'prevText' )
1623 ),
1624 'nextText' => array(
1625 'priority' => 160,
1626 'type' => 'text',
1627 'label' => __( "Next text", "ml-slider" ),
1628 'class' => 'option coin flex responsive nivo',
1629 'helptext' => __( "Set the text for the 'next' direction item", "ml-slider" ),
1630 'value' => $this->slider->get_setting( 'nextText' ) == 'false' ? '' : $this->slider->get_setting( 'nextText' )
1631 ),
1632 'sDelay' => array(
1633 'priority' => 170,
1634 'type' => 'number',
1635 'size' => 3,
1636 'min' => 0,
1637 'max' => 500,
1638 'step' => 10,
1639 'value' => $this->slider->get_setting( 'sDelay' ),
1640 'label' => __( "Square delay", "ml-slider" ),
1641 'class' => 'option coin',
1642 'helptext' => __( "Delay between squares in ms", "ml-slider" ),
1643 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1644 ),
1645 'opacity' => array(
1646 'priority' => 180,
1647 'type' => 'number',
1648 'size' => 3,
1649 'min' => 0,
1650 'max' => 1,
1651 'step' => 0.1,
1652 'value' => $this->slider->get_setting( 'opacity' ),
1653 'label' => __( "Opacity", "ml-slider" ),
1654 'class' => 'option coin',
1655 'helptext' => __( "Opacity of title and navigation", "ml-slider" ),
1656 'after' => ''
1657 ),
1658 'titleSpeed' => array(
1659 'priority' => 190,
1660 'type' => 'number',
1661 'size' => 3,
1662 'min' => 0,
1663 'max' => 10000,
1664 'step' => 100,
1665 'value' => $this->slider->get_setting( 'titleSpeed' ),
1666 'label' => __( "Caption speed", "ml-slider" ),
1667 'class' => 'option coin',
1668 'helptext' => __( "Set the fade in speed of the caption", "ml-slider" ),
1669 'after' => _x("ms", "Short for milliseconds", "ml-slider")
1670 ),
1671 'developerOptions' => array(
1672 'priority' => 195,
1673 'type' => 'divider',
1674 'class' => 'option coin flex responsive nivo',
1675 'value' => __( "Developer options", "ml-slider" )
1676 ),
1677 'cssClass' => array(
1678 'priority' => 200,
1679 'type' => 'text',
1680 'label' => __( "CSS classes", "ml-slider" ),
1681 'class' => 'option coin flex responsive nivo',
1682 'helptext' => __( "Specify any custom CSS Classes you would like to be added to the slider wrapper", "ml-slider" ),
1683 'value' => $this->slider->get_setting( 'cssClass' ) == 'false' ? '' : $this->slider->get_setting( 'cssClass' )
1684 ),
1685 'printCss' => array(
1686 'priority' => 210,
1687 'type' => 'checkbox',
1688 'label' => __( "Print CSS", "ml-slider" ),
1689 'class' => 'option coin flex responsive nivo useWithCaution',
1690 'checked' => $this->slider->get_setting( 'printCss' ) == 'true' ? 'checked' : '',
1691 'helptext' => __( "Uncheck this is you would like to include your own CSS", "ml-slider" )
1692 ),
1693 'printJs' => array(
1694 'priority' => 220,
1695 'type' => 'checkbox',
1696 'label' => __( "Print JS", "ml-slider" ),
1697 'class' => 'option coin flex responsive nivo useWithCaution',
1698 'checked' => $this->slider->get_setting( 'printJs' ) == 'true' ? 'checked' : '',
1699 'helptext' => __( "Uncheck this is you would like to include your own Javascript", "ml-slider" )
1700 ),
1701 'noConflict' => array(
1702 'priority' => 230,
1703 'type' => 'checkbox',
1704 'label' => __( "No conflict mode", "ml-slider" ),
1705 'class' => 'option flex',
1706 'checked' => $this->slider->get_setting( 'noConflict' ) == 'true' ? 'checked' : '',
1707 'helptext' => __( "Delay adding the flexslider class to the slideshow", "ml-slider" )
1708 ),
1709 );
1710
1711 $aFields = apply_filters( 'metaslider_advanced_settings', $aFields, $this->slider );
1712
1713 echo $this->build_settings_rows( $aFields );
1714 ?>
1715 </tbody>
1716 </table>
1717 </div>
1718 </div>
1719
1720 <?php $url = wp_nonce_url(admin_url("admin-post.php?action=metaslider_delete_slider&amp;slider_id={$this->slider->id}"), "metaslider_delete_slider"); ?>
1721 <div class="ms-delete-save">
1722 <a @click="deleteSlideshow" class='ms-delete-slideshow' href='<?php echo $url ?>'>Delete</a>
1723 <button class='button button-primary' type='submit' name='save'>
1724 <?php _e("Save slideshow", "ml-slider"); ?>
1725 </button>
1726 <span class="spinner" style="display: none;"></span>
1727 </div>
1728 </div>
1729 <?php } ?>
1730 </div>
1731 </div>
1732 </div>
1733 </form>
1734 <metaslider-import-module></metaslider-import-module>
1735 </div>
1736 </metaslider>
1737 </div>
1738 <?php
1739 }
1740
1741 /**
1742 * Append the 'Add Slider' button to selected admin pages
1743 *
1744 * @param string $context HTML being passed to amend HTML button
1745 * @return string HTML button
1746 */
1747 public function insert_metaslider_button($context) {
1748
1749 $capability = apply_filters( 'metaslider_capability', 'edit_others_posts' );
1750
1751 if ( ! current_user_can( $capability ) ) {
1752 return $context;
1753 }
1754
1755 global $pagenow;
1756
1757 if ( in_array( $pagenow, array( 'post.php', 'page.php', 'post-new.php', 'post-edit.php' ) ) ) {
1758 $context .= '<a href="#TB_inline?&inlineId=choose-meta-slider" class="thickbox button" title="' .
1759 __( "Select slideshow to insert into post", "ml-slider" ) .
1760 '"><span class="wp-media-buttons-icon" style="background: url(' . METASLIDER_ASSETS_URL .
1761 '/metaslider/matchalabs.png); background-repeat: no-repeat; background-position: left bottom;"></span> ' .
1762 __( "Add slider", "ml-slider" ) . '</a>';
1763 }
1764
1765 return $context;
1766
1767 }
1768
1769
1770 /**
1771 * Append the 'Choose MetaSlider' thickbox content to the bottom of selected admin pages
1772 */
1773 public function admin_footer() {
1774
1775 global $pagenow;
1776
1777 // Only run in post/page creation and edit screens
1778 if ( in_array( $pagenow, array( 'post.php', 'page.php', 'post-new.php', 'post-edit.php' ) ) ) {
1779 $sliders = $this->all_meta_sliders( 'title' );
1780 ?>
1781
1782 <script>
1783 jQuery(document).ready(function() {
1784 jQuery('#insertMetaSlider').on('click', function() {
1785 var id = jQuery('#metaslider-select option:selected').val();
1786 window.send_to_editor('[metaslider id=' + id + ']');
1787 tb_remove();
1788 })
1789 });
1790 </script>
1791
1792 <div id="choose-meta-slider" style="display: none;">
1793 <div class="wrap">
1794 <?php
1795 if ( count( $sliders ) ) {
1796 echo "<h3 style='margin-bottom: 20px;'>" . _x("Insert MetaSlider", 'Keep the plugin name "MetaSlider" when possible', "ml-slider") . "</h3>";
1797 echo "<select id='metaslider-select'>";
1798 echo "<option disabled=disabled>" . __( "Choose slideshow", "ml-slider" ) . "</option>";
1799 foreach ( $sliders as $slider ) {
1800 echo "<option value='{$slider['id']}'>{$slider['title']}</option>";
1801
1802 }
1803 echo "</select>";
1804 echo "<button class='button primary' id='insertMetaSlider'>" . __( "Insert slideshow", "ml-slider" ) . "</button>";
1805 } else {
1806 _e( "No slideshows found", "ml-slider" );
1807 }
1808 ?>
1809 </div>
1810 </div>
1811
1812 <?php
1813 }
1814 }
1815
1816
1817 /**
1818 * Return the MetaSlider pro upgrade iFrame
1819 */
1820 public function upgrade_to_pro_tab_layer() {
1821 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
1822 return wp_iframe(array($this, 'upgrade_to_pro_iframe_layer'));
1823 }
1824 }
1825
1826 /**
1827 * Media Manager iframe HTML - vimeo
1828 */
1829 public function upgrade_to_pro_iframe_layer() {
1830 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1831 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-layer&amp;utm_campaign=pro';
1832 $this->upgrade_to_pro_iframe(
1833 array(
1834 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/layers.png' alt='' />",
1835 "<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>",
1836 "<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>",
1837 "<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>",
1838 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
1839 )
1840 );
1841 }
1842
1843 /**
1844 * Return the MetaSlider pro upgrade iFrame for Vimeo
1845 */
1846 public function upgrade_to_pro_tab_vimeo() {
1847 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
1848 return wp_iframe(array($this, 'upgrade_to_pro_iframe_vimeo'));
1849 }
1850 }
1851
1852 /**
1853 * Media Manager iframe HTML - vimeo
1854 */
1855 public function upgrade_to_pro_iframe_vimeo() {
1856 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1857 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-vimeo&amp;utm_campaign=pro';
1858 $this->upgrade_to_pro_iframe(
1859 array(
1860 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/vimeo.png' alt='' />",
1861 "<h3>" . __('Create a slideshow full of your favorite videos easily and quickly by simply adding a URL to a Vimeo slide.', 'ml-slider') . "</h3>",
1862 "<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>",
1863 "<p>" . __('You could even have the slider autoplay a video, giving you a smooth, completely automatic presentation!', 'ml-slider') . "</p>",
1864 "<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>",
1865 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
1866 )
1867 );
1868 }
1869
1870 /**
1871 * Return the MetaSlider pro upgrade iFrame
1872 */
1873 public function upgrade_to_pro_tab_youtube() {
1874 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
1875 return wp_iframe(array($this, 'upgrade_to_pro_iframe_youtube'));
1876 }
1877 }
1878 /**
1879 * Media Manager iframe HTML - youtube
1880 */
1881 public function upgrade_to_pro_iframe_youtube() {
1882 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1883 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-youtube&amp;utm_campaign=pro';
1884 $this->upgrade_to_pro_iframe(
1885 array(
1886 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/youtube.png' alt='' />",
1887 "<h3>" . __('Create a slideshow full of your favorite videos easily and quickly by simply adding a URL to a YouTube slide.', 'ml-slider') . "</h3>",
1888 "<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>",
1889 "<p>" . __('You could even have the slider autoplay a video, giving you a smooth, completely automatic presentation!', 'ml-slider') . "</p>",
1890 "<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>",
1891 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
1892 )
1893 );
1894 }
1895 /**
1896 * Return the MetaSlider pro upgrade iFrame
1897 */
1898 public function upgrade_to_pro_tab_post_feed() {
1899 if (function_exists('is_plugin_active') && ! is_plugin_active('ml-slider-pro/ml-slider-pro.php')) {
1900 return wp_iframe(array($this, 'upgrade_to_pro_iframe_post_feed'));
1901 }
1902 }
1903 /**
1904 * Media Manager iframe HTML - post_feed
1905 */
1906 public function upgrade_to_pro_iframe_post_feed() {
1907 $link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1908 $link .= '?utm_source=lite&amp;utm_medium=more-slide-types-feed&amp;utm_campaign=pro';
1909 $this->upgrade_to_pro_iframe(
1910 array(
1911 "<img src='" . METASLIDER_ADMIN_URL . "images/upgrade/post-feed.png' alt='' />",
1912 "<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>",
1913 "<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>",
1914 "<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>",
1915 "<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>",
1916 "<span class='subtext'>" . __('Opens in a new window', 'ml-slider') . "</span>"
1917 )
1918 );
1919 }
1920
1921 /**
1922 * Upgrade to pro Iframe - Render
1923 *
1924 * @param string $content The HTML to render
1925 */
1926 public function upgrade_to_pro_iframe($content) {
1927 wp_enqueue_style('metaslider-admin-styles', METASLIDER_ADMIN_URL . 'assets/css/admin.css', false, METASLIDER_VERSION);
1928 wp_enqueue_script('google-font-api', 'https://fonts.googleapis.com/css?family=PT+Sans:400,700' , false, METASLIDER_VERSION);
1929
1930 echo "<div class='metaslider_pro'>";
1931 echo implode("", $content);
1932 echo "</div>";
1933 }
1934
1935 /**
1936 * Provide a tip so the user can add the slideshow to thier site
1937 *
1938 * @return string the tip
1939 */
1940 public function shortcode_tip() {
1941 // Title
1942 return '<h3 class="hndle metaslider-shortcode-title"><span>' . __("How to Use", "ml-slider") . '</span>' .
1943
1944 // Switch to title button
1945 '<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>' .
1946
1947 // Copy all button
1948 '<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>' .
1949
1950 '</h3>' .
1951
1952 // Container
1953 '<div class="inside wp-clearfix metaslider-shortcode">' .
1954
1955 // Description
1956 '<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>' .
1957
1958 // Shortcode
1959 '<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>' .
1960
1961 '</div>';
1962 }
1963
1964 /**
1965 * Adds extra links to the plugin activation page
1966 *
1967 * @param array $meta Extra meta links
1968 * @param string $file Specific file to compare against the base plugin
1969 * @param string $data Data for the meat links
1970 * @param string $status Staus of the meta links
1971 * @return array Return the meta links array
1972 */
1973 public function get_extra_meta_links($meta, $file, $data, $status) {
1974
1975 if (plugin_basename(__FILE__) == $file) {
1976 $plugin_page = admin_url('admin.php?page=metaslider');
1977 $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>";
1978 if (metaslider_pro_is_installed()) {
1979 $meta[] = "<a href='https://www.metaslider.com/support/' target='_blank'>" . __('Premium Support', 'ml-slider') . "</a>";
1980 } else {
1981 $upgrade_link = apply_filters('metaslider_hoplink', 'https://www.metaslider.com/upgrade/');
1982 $meta[] = "<a href='{$upgrade_link}' target='_blank'>" . __('Add-ons', 'ml-slider') . "</a>";
1983 $meta[] = "<a href='https://wordpress.org/support/plugin/ml-slider/' target='_blank'>" . __('Support', 'ml-slider') . "</a>";
1984 }
1985 $meta[] = "<a href='https://www.metaslider.com/documentation/' target='_blank'>" . __('Documentation', 'ml-slider') . "</a>";
1986 $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>";
1987 }
1988 return $meta;
1989 }
1990
1991 /**
1992 * Adds styles to admin head to allow for stars animation and coloring
1993 */
1994 public function add_star_styles() {
1995 if (metaslider_user_is_on_admin_page('plugins.php')) {?>
1996 <style>
1997 .ml-stars{display:inline-block;color:#ffb900;position:relative;top:3px}
1998 .ml-stars svg{fill:#ffb900}
1999 .ml-stars svg:hover{fill:#ffb900}
2000 .ml-stars svg:hover ~ svg{fill:none}
2001 </style>
2002 <?php }
2003 }
2004
2005 /**
2006 * Add nonce to activation pa
2007 */
2008 public function add_tour_nonce_to_activation_page() {
2009 if (metaslider_user_is_on_admin_page('plugins.php')) {?>
2010 <script>
2011 var metaslider_tour_nonce = "<?php echo wp_create_nonce('metaslider_tour_nonce'); ?>";
2012 </script>
2013 <?php }
2014 }
2015
2016 /**
2017 * Toggle Layout Buttons.
2018 *
2019 * @return string returns html button
2020 */
2021 public function toggle_layout_button() {
2022
2023 // Don't show this if there are no slideshows
2024 if (!count($this->all_meta_sliders())) {
2025 return '';
2026 }
2027
2028 $view = ('tabs' == $this->get_view()) ? 'tabs' : 'dropdown';
2029 $view_opposite = ('dropdown' == $this->get_view()) ? 'tabs' : 'dropdown';
2030 $instructions = ($this->get_view() == 'tabs') ? __("Switch to dropdown view", "ml-slider") : __("Switch to tabs view", "ml-slider");
2031 $url = admin_url("admin-post.php?action=metaslider_switch_view&view=" . $view_opposite);
2032 return "<a class='toggle-nav-view tipsy-tooltip' title='{$instructions}' href='{$url}'><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></a>";
2033 }
2034
2035 /**
2036 * Add a 'property=stylesheet' attribute to the MetaSlider CSS links for HTML5 validation
2037 *
2038 * @since 3.3.4
2039 * @param string $tag Specifies tag
2040 * @param string $handle Checks for the handle to add property to
2041 * @return string
2042 */
2043 public function add_property_attribute_to_stylesheet_links( $tag, $handle ) {
2044
2045 if ( strpos( $handle, 'metaslider' ) !== FALSE && strpos( $tag, "property='" ) === FALSE ) {
2046 // we're only filtering tags with metaslider in the handle, and links which don't already have a property attribute
2047 $tag = str_replace( "/>", "property='stylesheet' />", $tag );
2048 }
2049
2050 return $tag;
2051
2052 }
2053
2054 }
2055
2056 endif;
2057
2058 add_action('plugins_loaded', array(MetaSliderPlugin::get_instance(), 'setup'), 10);
2059