Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .cursor/rules/cimo-project-repos.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
description: Cimo project GitHub repos, roadmap, and free/premium structure
alwaysApply: true
---

# Cimo Project & Repositories

## Release Roadmap

The issues list, organized by targeted release version number, is the **Cimo Release Roadmap**:
https://github.com/orgs/gambitph/projects/12/views/1

## Repositories

This project has two GitHub repositories, used depending on whether we're building the **free** or **premium** version of Cimo.

### Free version

- Main plugin repo: https://github.com/gambitph/Cimo

### Premium version

- Uses the free version as the main plugin repo, and additionally uses:
- Premium-only repo: https://github.com/bfintal/cimo-premium
- The premium repo contains **only** the premium plugin code.
- It is placed in the `pro__premium_only` directory inside the free plugin's root folder.
1 change: 1 addition & 0 deletions cimo.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
require_once __DIR__ . '/src/admin/class-meta-box.php';
require_once __DIR__ . '/src/admin/class-metadata.php';
require_once __DIR__ . '/src/admin/class-admin-notices.php';
require_once __DIR__ . '/src/admin/class-bulk-library.php';
require_once __DIR__ . '/src/admin/class-stats.php';
require_once __DIR__ . '/src/admin/class-admin.php';

Expand Down
1 change: 1 addition & 0 deletions scripts/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,4 +389,5 @@ async function packagePlugin() {
packagePlugin().catch( err => {
// eslint-disable-next-line no-console
console.error( err )
process.exit( 1 )
} )
175 changes: 172 additions & 3 deletions src/admin/class-admin-notices.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@

if ( ! class_exists( 'Cimo_Admin_Notices' ) ) {
class Cimo_Admin_Notices {
const RATING_SNOOZE_TRANSIENT = 'cimo_rating_snooze';
const RATING_MIN_BYTES = 5242880; // 5 MB

public function __construct() {
add_action( 'admin_notices', [ $this, 'show_rating_notice' ] );
add_action( 'wp_ajax_cimo_rating_snooze', [ $this, 'ajax_rating_snooze' ] );
add_action( 'wp_ajax_cimo_rating_dismiss', [ $this, 'ajax_rating_dismiss' ] );

if ( CIMO_BUILD === 'free' ) {
add_action( 'admin_notices', [ $this, 'show_activation_notice' ] );
add_action( 'admin_notices', [ $this, 'show_library_premium_notice' ], 15 );
Expand All @@ -19,6 +26,149 @@ public function __construct() {
}
}

/**
* Site-wide ask for a WP.org review once the site has saved ≥ 5 MB.
*/
public function show_rating_notice() {
if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
return;
}

if ( '1' === get_option( 'cimo_rating_dismissed', '0' ) ) {
return;
}

if ( get_transient( self::RATING_SNOOZE_TRANSIENT ) ) {
return;
}

$bytes_saved = Cimo_Stats::get_bytes_saved();
if ( $bytes_saved < self::RATING_MIN_BYTES ) {
return;
}

$savings_label = Cimo_Stats::format_bytes( $bytes_saved, 1 );
$review_url = 'https://wordpress.org/support/plugin/cimo-image-optimizer/reviews/#new-post';
$nonce = wp_create_nonce( 'cimo_rating_notice' );
?>
<div class="notice notice-info cimo-rating-admin-notice" data-nonce="<?php echo esc_attr( $nonce ); ?>">
<p>
<?php
printf(
/* translators: %s is a human-readable size, e.g. "12.4 MB" */
esc_html__( 'You\'ve saved %s by optimizing media with Cimo, mind leaving a quick review?', 'cimo-image-optimizer' ),
'<strong>' . esc_html( $savings_label ) . '</strong>'
);
?>
</p>
<p class="cimo-rating-admin-notice-actions" style="margin-top: 16px;">
<a
href="<?php echo esc_url( $review_url ); ?>"
class="button button-primary"
target="_blank"
rel="noopener noreferrer"
><?php esc_html_e( 'Rate Now', 'cimo-image-optimizer' ); ?></a>
<button type="button" class="button button-secondary cimo-rating-snooze">
<?php esc_html_e( 'Remind me later', 'cimo-image-optimizer' ); ?>
</button>
<button type="button" class="button-link cimo-rating-dismiss">
<?php esc_html_e( 'Don\'t ask again', 'cimo-image-optimizer' ); ?>
</button>
</p>
</div>
<script>
(function() {
document.addEventListener('DOMContentLoaded', function() {
var notice = document.querySelector('.cimo-rating-admin-notice');
if (!notice || notice.getAttribute('data-bound') === '1') {
return;
}
notice.setAttribute('data-bound', '1');
var nonce = notice.getAttribute('data-nonce');
var busy = false;

function postAction(action, onSuccess) {
if (busy) {
return;
}
busy = true;
fetch(ajaxurl, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'action=' + encodeURIComponent(action) + '&nonce=' + encodeURIComponent(nonce)
}).then(function(response) {
if (!response.ok) {
throw new Error('Network response was not ok');
}
onSuccess();
}).catch(function(error) {
console.error('Cimo rating notice error:', error);
busy = false;
});
}

notice.addEventListener('click', function(event) {
if (event.target.classList.contains('cimo-rating-snooze')) {
event.preventDefault();
postAction('cimo_rating_snooze', function() {
notice.remove();
});
} else if (event.target.classList.contains('cimo-rating-dismiss')) {
event.preventDefault();
postAction('cimo_rating_dismiss', function() {
notice.remove();
});
}
});
});
})();
</script>
<style>
.cimo-rating-admin-notice-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
}
.cimo-rating-admin-notice-actions .cimo-rating-dismiss {
margin-left: 4px;
}
</style>
<?php
}

/**
* Snooze the rating notice for 30 days.
*/
public function ajax_rating_snooze() {
$this->verify_rating_notice_request();
set_transient( self::RATING_SNOOZE_TRANSIENT, 1, 30 * DAY_IN_SECONDS );
wp_send_json_success();
}

/**
* Permanently dismiss the rating notice.
*/
public function ajax_rating_dismiss() {
$this->verify_rating_notice_request();
update_option( 'cimo_rating_dismissed', '1', false );
delete_transient( self::RATING_SNOOZE_TRANSIENT );
wp_send_json_success();
}

/**
* Shared auth for rating notice AJAX actions.
*/
private function verify_rating_notice_request() {
$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
if ( ! $nonce || ! wp_verify_nonce( $nonce, 'cimo_rating_notice' ) ) {
wp_die( esc_html__( 'Security check failed.', 'cimo-image-optimizer' ) );
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'cimo-image-optimizer' ) );
}
}

/**
* Show the activation notice if it should be displayed.
*/
Expand Down Expand Up @@ -149,15 +299,34 @@ public function show_library_premium_notice() {

$nonce = wp_create_nonce( 'cimo_dismiss_library_premium_notice_ajax' );
$pricing = Cimo_Admin::pricing_url( 'library-admin-notice', 'admin' );
$savings_label = Cimo_Stats::get_additional_savings_estimate_label();
?>
<div class="notice notice-info is-dismissible cimo-library-premium-notice" data-nonce="<?php echo esc_attr( $nonce ); ?>">
<p>
<strong><?php esc_html_e( 'Cimo Premium: Optimize your entire media library', 'cimo-image-optimizer' ); ?></strong>
<strong>
<?php
if ( $savings_label !== '' ) {
esc_html_e( 'Your Media Library still has unoptimized images', 'cimo-image-optimizer' );
} else {
esc_html_e( 'Bulk optimize your entire Media Library', 'cimo-image-optimizer' );
}
?>
</strong>
</p>
<p>
<?php esc_html_e( 'You\'re optimizing images on upload. Extend this to bulk optimize your existing images and user uploads without using your server.', 'cimo-image-optimizer' ); ?>
<?php
if ( $savings_label !== '' ) {
printf(
/* translators: %s is a human-readable size, e.g. "12.4 MB" */
esc_html__( 'You\'re optimizing images on upload. Upgrade to Cimo premium to bulk optimize your entire media library and save %s more.', 'cimo-image-optimizer' ),
'<strong>' . esc_html( $savings_label ) . '</strong>'
);
} else {
esc_html_e( 'You\'re optimizing images on upload. Upgrade to Cimo premium to bulk optimize your entire media library.', 'cimo-image-optimizer' );
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
?>
</p>
<p>
<p style="margin-top: 16px;">
<a href="<?php echo esc_url( $pricing ); ?>" class="button button-primary" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Optimize entire library →', 'cimo-image-optimizer' ); ?></a>
</p>
</div>
Expand Down
1 change: 0 additions & 1 deletion src/admin/class-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ public function enqueue_admin_scripts( $hook ) {
wp_localize_script( 'cimo-admin-page', 'cimoAdmin', [
'stats' => $stats,
'imageSizes' => $formatted_sizes,
'ratingDismissed' => '1' === get_option( 'cimo_rating_dismissed', '0' ) ? '1' : '0',
'isPremium' => CIMO_BUILD === 'premium',
'uploadsUrl' => wp_upload_dir()['baseurl'],
] );
Expand Down
Loading
Loading