PluginProbe
picu – Online Photo Proofing Gallery / 2.2.0
picu – Online Photo Proofing Gallery v2.2.0
3.9.0 3.8.1 3.8.0 3.7.0 3.6.1 3.6.0 trunk 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.2.0 2.3.0 2.3.1.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 All 46 releases
picu / picu.php

picu.php in picu – Online Photo Proofing Gallery 2.2.0, at picu.php

538 lines 20.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: picu
4 * Plugin URI: https://picu.io/
5 * Description: Send a collection of photographs to your client for approval.
6 * Version: 2.2.0
7 * Requires at least: 6.0
8 * Requires PHP: 7.4
9 * Author: Haptiq
10 * Author URI: https://picu.io/
11 * License: GPLv3
12 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
13 * Text Domain: picu
14 */
15 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
16
17
18 /**
19 * Include functions for picu
20 *
21 * @since 0.2.0
22 */
23 if ( ! function_exists( 'picu_setup' ) ) {
24
25 function picu_setup() {
26
27 // Define plugin version
28 define( 'PICU_VERSION', '2.2.0' );
29
30 // Define path for this plugin
31 define( 'PICU_PATH', plugin_dir_path(__FILE__) );
32
33 // Define URL for this plugin
34 define( 'PICU_URL', plugin_dir_url(__FILE__) );
35
36 // Define picu upload dir
37 $upload_dir = wp_upload_dir();
38 define( 'PICU_UPLOAD_DIR', $upload_dir['basedir'] . '/picu' );
39
40 // Define telemetry URL
41 define( 'PICU_TELEMETRY_URL', 'https://picu.io/wp-json/picu-telemetry/v1/' );
42
43 // Include functions to render admin menu and settings page
44 require PICU_PATH . 'backend/includes/picu-settings.php';
45
46 // Include functions to render add-ons page
47 require PICU_PATH . 'backend/includes/picu-addons-page.php';
48
49 // Include function for registering custom post type collection
50 require PICU_PATH . 'backend/includes/picu-cpt-collection.php';
51
52 // Include welcome screen
53 require PICU_PATH . 'backend/includes/picu-welcome-screen.php';
54
55 // Include functions for admin notices and error messages
56 require PICU_PATH . 'backend/includes/picu-admin-notices.php';
57
58 // Include custom metabox and our custom edit screen
59 require PICU_PATH . 'backend/includes/picu-edit-collection.php';
60
61 // Picu media handling
62 require PICU_PATH . 'backend/includes/picu-media.php';
63
64 // Everything that doesn't fit anywhere else...
65 require PICU_PATH . 'backend/includes/picu-helper.php';
66
67 // Handle ajax requests
68 require PICU_PATH . 'backend/includes/picu-ajax.php';
69
70 // Fix third party stuff
71 require PICU_PATH . 'backend/includes/picu-opp.php';
72
73 // Picu Email sending class
74 require PICU_PATH . 'backend/includes/emails/class-picu-emails.php';
75
76 // Picu Email sending functions
77 require PICU_PATH . 'backend/includes/emails/picu-emails.php';
78
79 // Include template redirection etc. for collections
80 require PICU_PATH . 'frontend/includes/picu-template-functions.php';
81
82 // Deprecated functions, filters and hooks
83 require PICU_PATH . 'backend/includes/deprecated.php';
84
85 // Handle picu telemetry
86 require PICU_PATH . 'backend/includes/picu-telemetry.php';
87
88 // Autoload classes installed via composer (emogrify)
89 require PICU_PATH . 'vendor/autoload.php';
90
91 // Add picu debug info to Site Health screen
92 require PICU_PATH . 'backend/includes/picu-site-health.php';
93
94 // Check the settings version, run upgrader
95 $settings_version = get_option( 'picu_settings_version' );
96 // Version upgrade is needed
97 if ( empty( $settings_version ) ) {
98 picu_settings_upgrade();
99 }
100 }
101 }
102
103 add_action( 'after_setup_theme', 'picu_setup' );
104
105
106 /**
107 * Set transient to display welcome screen on activation
108 *
109 * @since 0.7.0
110 */
111 function picu_activate_welcome_screen() {
112 // Set transient for redirect to activation screen
113 set_transient( '_picu_welcome_screen_activation_redirect', true, 30 );
114 }
115
116 register_activation_hook( __FILE__, 'picu_activate_welcome_screen' );
117
118
119 /**
120 * Flush rewrite rules on plugin activation/deactivation
121 *
122 * @since 0.7.0
123 */
124 function picu_flush_rewrites() {
125
126 // Include custom post type registration
127 include( plugin_dir_path(__FILE__) . 'backend/includes/picu-cpt-collection.php' );
128
129 // Make sure our custom post types are defined first
130 picu_register_cpt_collection();
131
132 // Flush the rewrite rules
133 flush_rewrite_rules();
134
135 }
136
137 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' );
138 register_activation_hook( __FILE__, 'picu_flush_rewrites' );
139
140
141 /**
142 * Load some custom styling for our admin screens.
143 *
144 * @since 0.3.2
145 */
146 function picu_admin_styles_scripts() {
147
148 global $post;
149
150 $current_screen = get_current_screen();
151
152 // Prevent conflicts in case no current_screen is set
153 if ( empty( $current_screen ) ) {
154 return;
155 }
156
157 // Only load those styles on edit collection screens
158 if ( is_admin() ) {
159 wp_enqueue_style( 'picu-admin', PICU_URL . 'backend/css/picu-admin.css', false, filemtime( PICU_PATH . 'backend/css/picu-admin.css' ) );
160
161 global $pagenow;
162 if ( $current_screen->post_type == 'picu_collection' AND get_post_type() == 'picu_collection' AND $pagenow == 'post-new.php' || $pagenow == 'post.php' ) {
163 // Enqueue wp.media scripts manually, because we don't load the default editor on collections
164 // Post needs to be provided, or uploaded media will not get attached to the collection
165 $args = array( 'post' => $post->ID );
166 wp_enqueue_media( $args );
167 }
168
169 if ( $current_screen->base == 'picu_page_picu-design-appearance' ) {
170 // Add the color picker css file
171 wp_enqueue_style( 'wp-color-picker' );
172 }
173
174 // Make sure we are on the right screen
175 if ( ( $current_screen->post_type == 'picu_collection' && get_post_type() == 'picu_collection' && $pagenow == 'post-new.php' || $pagenow == 'post.php' ) || ( $current_screen->base == 'dashboard_page_picu-welcome-screen' ) || ( $current_screen->post_type == 'picu_collection' AND get_post_type() == 'picu_collection' AND $pagenow == 'edit.php' ) || strpos( $current_screen->base, 'picu_page_picu-' ) !== false ) {
176
177 // Enqueue media
178 wp_enqueue_media();
179
180 // Enqueue script
181 wp_enqueue_script( 'picu-admin', PICU_URL . 'backend/js/picu-admin.min.js', array( 'jquery', 'jquery-ui-draggable', 'jquery-ui-sortable', 'underscore', 'backbone', 'wp-color-picker' ), filemtime( PICU_PATH . 'backend/js/picu-admin.min.js' ), true );
182
183 $post_id = false;
184 if ( isset( $post->ID ) AND ! empty( $post->ID ) ) {
185 $post_id = $post->ID;
186 }
187
188 // Localize it
189 $picu_localization_strings = array(
190 'ajaxurl' => admin_url( 'admin-ajax.php' ),
191 'ajax_nonce' => wp_create_nonce( 'picu_ajax' ),
192 'postID' => $post_id,
193 'media_modal_title' => __( 'Upload Images', 'picu' ),
194 'media_modal_button_insert_text' => __( 'Insert Images', 'picu' ),
195 'sent_option_label' => __( 'Sent', 'picu' ),
196 'approved_option_label' => __( 'Approved', 'picu' ),
197 'expired_option_label' => __( 'Expired', 'picu' ),
198 'button_text_publish' => __( 'Publish', 'picu' ),
199 'button_text_send_to_client' => __( 'Send to Client', 'picu' ),
200 'selection_table_no_match' => __( 'No images found', 'picu' ),
201 );
202
203 $picu_localization_strings = apply_filters( 'picu_localization_strings', $picu_localization_strings );
204
205 wp_localize_script( 'picu-admin', 'picu_admin', $picu_localization_strings );
206 }
207
208 }
209
210 }
211
212 add_action( 'admin_enqueue_scripts', 'picu_admin_styles_scripts' );
213
214
215 /**
216 * Add settings link in plugins overview
217 *
218 * @param array $actions An array of links
219 * @since 1.0.0
220 */
221 function picu_plugin_action_links( $actions ) {
222
223 $action = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=picu-settings' ), __( 'Settings', 'picu' ) );
224 array_unshift( $actions, $action );
225
226 return $actions;
227 }
228
229 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ) , 'picu_plugin_action_links', 10 );
230
231
232 /**
233 * Custom capability to manage picu collections.
234 *
235 * Defaults to administrator privileges, can be filtered using 'picu_capability'.
236 *
237 * @since 1.1.0
238 */
239 function picu_capability() {
240 $picu_capability = 'manage_options';
241 $picu_capability = apply_filters( 'picu_capability', $picu_capability );
242
243 return $picu_capability;
244 }
245
246
247 /**
248 * Redirect /picu to collection overview in WordPress admin
249 *
250 * @since 1.2.1
251 */
252 function picu_redirect_to_overview() {
253 if ( $_SERVER['REQUEST_URI'] == '/picu' OR $_SERVER['REQUEST_URI'] == '/picu/' ) {
254 wp_redirect( admin_url() . 'edit.php?post_type=picu_collection' );
255 exit;
256 }
257 }
258
259 add_action( 'init', 'picu_redirect_to_overview' );
260
261
262 /**
263 * Check picu Pro compatibility
264 *
265 * @since 2.0.0
266 */
267 function picu_check_pro_compat() {
268 if ( defined( 'PICU_PRO' ) && version_compare( PICU_PRO, '1.1.0' ) < 0 ) {
269 /* translators: Admin notice, %s = opening and closing link tags */
270 $notice = sprintf ( __( '🚨 <strong>Action required:</strong> The version of picu Pro you are using is not compatible with this version of picu. %sPlease update to the latest version of picu Pro%s.', 'picu' ), '<a href="' . admin_url( 'plugins.php?s=picu%20pro&plugin_status=all' ) . '">', '</a>' );
271 $notice_type = 'error';
272
273 // Display admin notice
274 add_action( 'admin_notices', function() use ( $notice, $notice_type ) {
275 ?>
276 <div class="picu-pro-module-notice notice notice-<?php echo $notice_type; ?>">
277 <p><?php echo $notice; ?></p>
278 </div>
279 <?php
280 });
281 }
282 }
283
284 add_action( 'init', 'picu_check_pro_compat' );
285
286
287 /**
288 * Add picu Pro upgrade box
289 *
290 * @since 1.3.1
291 */
292 function picu_add_pro_metabox() {
293 if ( ! picu_is_pro_license_valid() ) {
294
295 add_meta_box(
296 'picu-pro-metabox',
297 __( 'Get picu pro', 'picu' ),
298 'picu_display_pro_metabox',
299 'picu_collection',
300 'side',
301 'high'
302 );
303 }
304 }
305
306 add_action( 'add_meta_boxes', 'picu_add_pro_metabox' );
307
308
309 /**
310 * Render the Pro metabox.
311 *
312 * @since 1.3.1
313 * @since 2.0.0 New box design and content
314 */
315 function picu_display_pro_metabox() {
316 ?>
317 <div class="picu-pro-meta-box">
318 <img class="picu-pro-meta-box__image" src="<?php echo PICU_URL; ?>/backend/images/picu.png" alt="picu logo" />
319 <div class="picu-pro-meta-box__intro">
320 <h2 class="picu-pro-meta-box__title"><?php /* translators: %s = Openning and closing HTML tag */ echo sprintf( __( 'Get picu %sPro%s', 'picu' ), '<span class="picu-pro-pro">', '<span>' ); ?></h2>
321 </div>
322 <div class="picu-pro-meta-box__content">
323 <p><strong><?php _e( 'Take your proofing workflow to the next level:', 'picu' ); ?></strong></p>
324 <p><?php _e( 'Add personal branding, allow comments, add watermarks and many more features for professional photographers.', 'picu' ); ?></p>
325 <p class="picu-pro-meta-box__button-wrap"><a class="button button-primary picu-pro__button" href="https://picu.io/pro/?utm_source=picu_plugin&utm_medium=pro_metabox" target="_blank"><?php _e( 'Get picu Pro now', 'picu' ); ?> <svg style="transform: translateY(3px);" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#007791" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h13M12 5l7 7-7 7"/></svg></a></p>
326 <div class="picu-pro-meta-box__reviews">
327 <p>
328 <svg width="16" height="16" viewBox="0 0 16 15" xmlns="http://www.w3.org/2000/svg"><path d="m6.75365082.46448007c.30569615-.61930676 1.1888161-.61930676 1.49451225 0l1.86507723 3.77985326 4.1748568.61109495c.6453032.09432073.9240557.84870204.5363234 1.33810964l-.0754029.08342717-3.0197773 2.94036824.7130072 4.15513057c.1106198.6449702-.5249381 1.144844-1.1119645.922308l-.0972521-.0438773-3.73279062-1.9635613-3.73145727 1.9635613c-.57918124.3045856-1.25104449-.1453116-1.22088044-.7723782l.01166386-.1060525.71167385-4.15513057-3.018444-2.94036824c-.46718009-.45503341-.25023224-1.22945432.35090953-1.39822842l.11001096-.02330839 4.17352351-.61109495z" fill="#ffd700" transform="translate(.5 .5)"/></svg>
329 <svg width="16" height="16" viewBox="0 0 16 15" xmlns="http://www.w3.org/2000/svg"><path d="m6.75365082.46448007c.30569615-.61930676 1.1888161-.61930676 1.49451225 0l1.86507723 3.77985326 4.1748568.61109495c.6453032.09432073.9240557.84870204.5363234 1.33810964l-.0754029.08342717-3.0197773 2.94036824.7130072 4.15513057c.1106198.6449702-.5249381 1.144844-1.1119645.922308l-.0972521-.0438773-3.73279062-1.9635613-3.73145727 1.9635613c-.57918124.3045856-1.25104449-.1453116-1.22088044-.7723782l.01166386-.1060525.71167385-4.15513057-3.018444-2.94036824c-.46718009-.45503341-.25023224-1.22945432.35090953-1.39822842l.11001096-.02330839 4.17352351-.61109495z" fill="#ffd700" transform="translate(.5 .5)"/></svg>
330 <svg width="16" height="16" viewBox="0 0 16 15" xmlns="http://www.w3.org/2000/svg"><path d="m6.75365082.46448007c.30569615-.61930676 1.1888161-.61930676 1.49451225 0l1.86507723 3.77985326 4.1748568.61109495c.6453032.09432073.9240557.84870204.5363234 1.33810964l-.0754029.08342717-3.0197773 2.94036824.7130072 4.15513057c.1106198.6449702-.5249381 1.144844-1.1119645.922308l-.0972521-.0438773-3.73279062-1.9635613-3.73145727 1.9635613c-.57918124.3045856-1.25104449-.1453116-1.22088044-.7723782l.01166386-.1060525.71167385-4.15513057-3.018444-2.94036824c-.46718009-.45503341-.25023224-1.22945432.35090953-1.39822842l.11001096-.02330839 4.17352351-.61109495z" fill="#ffd700" transform="translate(.5 .5)"/></svg>
331 <svg width="16" height="16" viewBox="0 0 16 15" xmlns="http://www.w3.org/2000/svg"><path d="m6.75365082.46448007c.30569615-.61930676 1.1888161-.61930676 1.49451225 0l1.86507723 3.77985326 4.1748568.61109495c.6453032.09432073.9240557.84870204.5363234 1.33810964l-.0754029.08342717-3.0197773 2.94036824.7130072 4.15513057c.1106198.6449702-.5249381 1.144844-1.1119645.922308l-.0972521-.0438773-3.73279062-1.9635613-3.73145727 1.9635613c-.57918124.3045856-1.25104449-.1453116-1.22088044-.7723782l.01166386-.1060525.71167385-4.15513057-3.018444-2.94036824c-.46718009-.45503341-.25023224-1.22945432.35090953-1.39822842l.11001096-.02330839 4.17352351-.61109495z" fill="#ffd700" transform="translate(.5 .5)"/></svg>
332 <svg width="16" height="16" viewBox="0 0 16 15" xmlns="http://www.w3.org/2000/svg"><g fill="none" transform="translate(.5 .5)"><path d="m6.75365082.46448007c.30569615-.61930676 1.1888161-.61930676 1.49451225 0l1.86507723 3.77985326 4.1748568.61109495c.6453032.09432073.9240557.84870204.5363234 1.33810964l-.0754029.08342717-3.0197773 2.94036824.7130072 4.15513057c.1106198.6449702-.5249381 1.144844-1.1119645.922308l-.0972521-.0438773-3.73279062-1.9635613-3.73145727 1.9635613c-.57918124.3045856-1.25104449-.1453116-1.22088044-.7723782l.01166386-.1060525.71167385-4.15513057-3.018444-2.94036824c-.46718009-.45503341-.25023224-1.22945432.35090953-1.39822842l.11001096-.02330839 4.17352351-.61109495z" fill="#fffdf0"/><path d="m7.50024028.00000364v12.28732966l-3.73145727 1.9635613c-.57918124.3045856-1.25104449-.1453116-1.22088044-.7723782l.01166386-.1060525.71167385-4.15513057-3.018444-2.94036824c-.46718009-.45503341-.25023224-1.22945432.35090953-1.39822842l.11001096-.02330839 4.17352351-.61109495 1.86641054-3.77985326c.13336744-.27018775.37733399-.42249948.63539651-.45693517z" fill="#ffd700"/></g></svg>
333 <span class="picu-pro-meta-box__rating">4.7 / 5</span>
334 </p>
335 <p><strong><?php _e( 'Don\'t take our word for it.', 'picu' ); ?></strong></p>
336 <p><a class="picu-pro-meta-box__link" href="https://picu.io/reviews/?utm_source=picu_plugin&utm_medium=pro_metabox"><?php _e( 'Check out picu user reviews', 'picu' ); ?></a></p>
337 </div>
338 </div>
339 </div>
340 <?php
341 }
342
343
344 /**
345 * Hide admin bar for now
346 */
347 add_filter( 'picu_show_admin_bar', '__return_false' );
348
349
350 /**
351 * Check if collection slug has changed
352 *
353 * @since 1.5.0
354 */
355 function picu_check_collection_slug() {
356
357 // Only run if collection or 404
358 if ( 'picu_collection' != get_post_type() AND ! is_404() ) {
359 return;
360 }
361
362 // Only run, if pretty permalinks are active
363 if ( ! get_option( 'permalink_structure' ) ) {
364 return;
365 }
366
367 // Get current collection slug
368 $post_type = get_post_type_object( 'picu_collection' );
369 $post_type_slug = $post_type->rewrite['slug'];
370
371 // Get saved slug. Set, if empty
372 $saved_slug = get_transient( 'picu_collection_slug' );
373
374 if ( empty( $saved_slug ) ) {
375 set_transient( 'picu_collection_slug', $post_type_slug, 0 );
376 return;
377 }
378
379 // Compare current with saved collection slug
380 if ( $post_type_slug != $saved_slug ) {
381 $old_picu_slugs = get_transient( 'picu_collection_old_slugs' );
382 $old_picu_slugs[] = $saved_slug;
383 set_transient( 'picu_collection_old_slugs', array_unique( $old_picu_slugs ) );
384 set_transient( 'picu_collection_slug', $post_type_slug, 0 );
385 flush_rewrite_rules( false );
386 }
387 }
388
389 add_action( 'wp', 'picu_check_collection_slug' );
390
391
392 /**
393 * Redirect when old collection base slug is used
394 *
395 * @since 1.5.0
396 */
397 function picu_redirect_from_old_slug() {
398
399 // Only run, if this is a 404
400 if ( ! is_404() ) {
401 return;
402 }
403
404 // Only run, if pretty permalinks are active
405 if ( ! get_option( 'permalink_structure' ) ) {
406 return;
407 }
408
409 // Check if the old slug transient is set
410 $old_picu_slugs = get_transient( 'picu_collection_old_slugs' );
411
412 if ( empty( $old_picu_slugs ) ) {
413 return;
414 }
415
416 // Get current url & path
417 global $wp;
418 $current_url = home_url( $wp->request );
419 $url = parse_url( $current_url );
420 $path = '';
421 if ( ! empty( $url['path'] ) ) {
422 $path = explode( '/', $url['path'] );
423 }
424
425 // Get current picu collection slug
426 $post_type_object = get_post_type_object( 'picu_collection' );
427 $current_slug = $post_type_object->rewrite['slug'];
428
429 if ( empty( $path[1] ) OR ! in_array( $path[1], $old_picu_slugs ) OR $path[1] == $current_slug ) {
430 return;
431 }
432
433 // Replace old slug with the new one
434 $new_url = $url['scheme'] . '://' . $url['host'] . '/' . $current_slug . '/' . $path[2] . '/';
435
436 // Get post type by url for the collection
437 $post_type = get_post_type( url_to_postid( $new_url ) );
438
439 // Redirect if the url is actually a collection
440 if ( 'picu_collection' == $post_type ) {
441 wp_redirect( trailingslashit( $new_url ), 301 );
442 }
443 }
444
445 add_filter( 'wp', 'picu_redirect_from_old_slug' );
446
447
448 /**
449 * Initialize proof file download
450 *
451 * @since 1.5.0
452 */
453 function picu_trigger_proof_file_download() {
454 if ( ! empty( $_REQUEST['picu-download'] ) AND $_REQUEST['picu-download'] == 'picu-proof-file' ) {
455 picu_create_proof_file( $_REQUEST['post'] );
456 exit;
457 }
458 }
459
460 add_action( 'init', 'picu_trigger_proof_file_download' );
461
462
463 /**
464 * Display Pro hint between image upload and sharing options
465 *
466 * @since 1.6.0
467 */
468 function picu_display_pro_hint() {
469 if ( ! picu_is_pro_active() ) {
470
471 $pro_hints = array(
472 /* translators: Opening and closing link tags */
473 sprintf( __( 'Allow your clients to add comments & markers on individual images with %spicu Pro%s.', 'picu' ), ' <a href="https://picu.io/pro/mark-and-comment/?utm_source=picu_plugin&utm_medium=pro_hints" target="_blank">', '</a>' ),
474 /* translators: Opening and closing link tags */
475 sprintf( __( 'Import a huge number of images directly from your web server with %spicu Pro%s.', 'picu' ), '<a href="https://picu.io/pro/import/?utm_source=picu_plugin&utm_medium=pro_hints" target="_blank">', '</a>' ),
476 /* translators: Opening and closing link tags */
477 sprintf( __( 'Protect your images with a watermark with %spicu Pro%s.', 'picu' ), ' <a href="https://picu.io/pro/theft-protection/?utm_source=picu_plugin&utm_medium=pro_hints" target="_blank">', '</a>' ),
478 /* translators: Opening and closing link tags */
479 sprintf( __( 'Define the exact number of images your clients need to select with %spicu Pro%s.', 'picu' ), ' <a href="https://picu.io/pro/selection-options/?utm_source=picu_plugin&utm_medium=pro_hints" target="_blank">', '</a>' ),
480 /* translators: Opening and closing link tags */
481 sprintf( __( 'Allow your clients to download proofing images from your collections with %spicu Pro%s.', 'picu' ), ' <a href="https://picu.io/pro/download/?utm_source=picu_plugin&utm_medium=pro_hints" target="_blank">', '</a>' ),
482 /* translators: Opening and closing link tags */
483 sprintf( __( 'Deliver your final images to your clients with %spicu Pro%s.', 'picu' ), ' <a href="https://picu.io/pro/delivery/?utm_source=picu_plugin&utm_medium=pro_hints" target="_blank">', '</a>' ),
484 );
485
486 // Randomize which pro hint to display
487 $display_pro_hint = rand( 1, count( $pro_hints ) ) - 1;
488 ?>
489 <div class="picu-pro-hint">
490 <div class="picu-pro-hint-inner">
491 <span class="picu-pro-hint-icon">👀</span>
492 <div class="picu-pro-hint-content">
493 <?php echo $pro_hints[$display_pro_hint]; ?>
494 </div>
495 </div>
496 </div>
497 <?php
498 }
499 }
500
501
502 /**
503 * Determine if Pro is active and license is valid.
504 *
505 * @since 1.6.0
506 * @since 1.9.0 Use function from Pro plugin, also checking license status
507 * @since 2.0.1 No longer checking license status
508 *
509 * @return bool Whether Pro is active or not
510 */
511 function picu_is_pro_active() {
512 if ( is_plugin_active( 'picu-pro/picu-pro.php' ) ) {
513 return true;
514 }
515
516 return false;
517 }
518
519
520 /**
521 * Determine if there is a valid Pro license.
522 *
523 * @since 2.0.1
524 *
525 * @return bool Whether there is an active Pro license
526 */
527 function picu_is_pro_license_valid() {
528 $valid = false;
529
530 if ( function_exists( 'picu_pro_get_license_status' ) ) {
531 $license_status = picu_pro_get_license_status();
532 if ( $license_status == 'valid' ) {
533 $valid = true;
534 }
535 }
536
537 return $valid;
538 }