Skip to content
Open
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
19 changes: 15 additions & 4 deletions php/class-connect.php
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,13 @@ function ( $a ) {
public function history( $days = 1 ) {
$return = array();
$history = get_option( self::META_KEYS['history'], array() );
$plan = ! empty( $this->usage['plan'] ) ? $this->usage['plan'] : $this->credentials['cloud_name'];
// Stored option can be a non-array if it was corrupted by a previous
// failed write. Reset to empty array to avoid string-offset fatals.
if ( ! is_array( $history ) ) {
$history = array();
}
$plan_source = is_array( $this->usage ) && ! empty( $this->usage['plan'] ) ? $this->usage['plan'] : '';
$plan = '' !== $plan_source ? $plan_source : ( isset( $this->credentials['cloud_name'] ) ? $this->credentials['cloud_name'] : '' );
for ( $i = 1; $i <= $days; $i++ ) {
$date = date_i18n( 'd-m-Y', strtotime( '- ' . $i . ' days' ) );
if ( ! isset( $history[ $plan ][ $date ] ) || is_wp_error( $history[ $plan ][ $date ] ) ) {
Expand Down Expand Up @@ -720,9 +726,14 @@ public function usage_stats( $refresh = false ) {
$last_usage = $this->settings->get_setting( 'last_usage' );
// Get users plan.
$stats = $this->api->usage();
if ( ! is_wp_error( $stats ) && ! empty( $stats['media_limits'] ) ) {
$stats['max_image_size'] = $stats['media_limits']['image_max_size_bytes'];
$stats['max_video_size'] = $stats['media_limits']['video_max_size_bytes'];
if (
! is_wp_error( $stats )
&& is_array( $stats )
&& isset( $stats['media_limits'] )
&& is_array( $stats['media_limits'] )
) {
$stats['max_image_size'] = isset( $stats['media_limits']['image_max_size_bytes'] ) ? $stats['media_limits']['image_max_size_bytes'] : 0;
$stats['max_video_size'] = isset( $stats['media_limits']['video_max_size_bytes'] ) ? $stats['media_limits']['video_max_size_bytes'] : 0;
$last_usage->save_value( $stats );// Save the last successful call to prevgent crashing.
} else {
// Handle error by logging and fetching the last success.
Expand Down
9 changes: 8 additions & 1 deletion php/class-cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,15 @@ public function rest_endpoints( $endpoints ) {
*/
protected function load_schedule() {
$this->schedule = get_option( self::CRON_META_KEY, array() );
// Guard against a corrupted option (e.g. a string was previously
// stored) so the foreach below cannot fatal on PHP 8.x.
if ( ! is_array( $this->schedule ) ) {
$this->schedule = array();
}
foreach ( $this->schedule as &$item ) {
$item['active'] = false;
if ( is_array( $item ) ) {
$item['active'] = false;
}
}
}

Expand Down
21 changes: 16 additions & 5 deletions php/class-media.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,15 +446,26 @@ public function is_oversize_media( $attachment_id ) {
return $is_oversize[ $attachment_id ];
}

$file_size = $this->get_attachment_file_size( $attachment_id );
$max_size = ( wp_attachment_is_image( $attachment_id ) ? 'image_max_size_bytes' : 'video_max_size_bytes' );
$limit = $this->plugin->components['connect']->usage['media_limits'][ $max_size ];
$file_size = $this->get_attachment_file_size( $attachment_id );
$max_size_key = ( wp_attachment_is_image( $attachment_id ) ? 'image_max_size_bytes' : 'video_max_size_bytes' );
$usage = $this->plugin->components['connect']->usage;
$media_limits = is_array( $usage ) && isset( $usage['media_limits'] ) ? $usage['media_limits'] : null;

// If the limit isn't available yet (e.g. plugin not connected, or API
// returned an unexpected response), treat the asset as not oversize
// rather than fatal-erroring on a string offset.
if ( ! is_array( $media_limits ) || ! isset( $media_limits[ $max_size_key ] ) ) {
$is_oversize[ $attachment_id ] = false;

return $is_oversize[ $attachment_id ];
}

$limit = $media_limits[ $max_size_key ];

$is_oversize[ $attachment_id ] = $file_size > $limit;

if ( $is_oversize[ $attachment_id ] ) {
$max_size = ( wp_attachment_is_image( $attachment_id ) ? 'image_max_size_bytes' : 'video_max_size_bytes' );
$max_size_hr = size_format( $this->plugin->components['connect']->usage['media_limits'][ $max_size ] );
$max_size_hr = size_format( $limit );
// translators: variable is file size.
$message = sprintf( __( 'File size exceeds the maximum of %s. This media asset will be served from WordPress.', 'cloudinary' ), $max_size_hr );
update_post_meta( $attachment_id, Sync::META_KEYS['sync_error'], $message );
Expand Down
6 changes: 6 additions & 0 deletions php/class-special-offer.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ public function filtered_settings( $settings ) {
protected function is_special_offer_available() {
$last_usage = get_option( Connect::META_KEYS['last_usage'], array( 'plan' => '' ) );

// `last_usage` can be a string when the usage API has never returned a
// valid response. Only an array with a `plan` key is meaningful here.
if ( ! is_array( $last_usage ) || ! isset( $last_usage['plan'] ) ) {
return false;
}

return 'free' === strtolower( $last_usage['plan'] );
}

Expand Down
5 changes: 5 additions & 0 deletions php/integrations/class-wpml.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ public function wp_generate_attachment_metadata( $metadata, $attachment_id, $con

$original_attachment_id = $attachment_id;
$data = get_transient( self::TRANSIENT_KEY );
// Cast to array to avoid string-offset fatals on PHP 8.x when the
// transient holds an unexpected scalar.
if ( ! is_array( $data ) ) {
$data = array();
}

// This is a duplicated attachment. Let's restore the metadata via WPML.
if ( ! empty( $data[ $original_attachment_id ] ) ) {
Expand Down
6 changes: 4 additions & 2 deletions php/sync/class-sync-queue.php
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,10 @@ public function get_thread_queue( $thread ) {
);
wp_cache_delete( $thread_option, 'options' );
$return = get_option( $thread_option );
if ( empty( $return ) ) {
// Set option to remove notoption and default fro cache.
if ( empty( $return ) || ! is_array( $return ) ) {
// Reset to default when missing or corrupted (e.g. a string was
// previously stored). Without the is_array check, array_merge
// below would fatal on PHP 8.x.
$this->set_thread_queue( $thread, $default );
$return = $default;
}
Expand Down
14 changes: 12 additions & 2 deletions php/ui/component/class-plan-details.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,28 @@ protected function plan( $struct ) {
return $struct;
}

// `last_usage` can be a string when the usage API has never returned a
// valid response (e.g. fresh install or API error). Without this
// guard, PHP 8.x fatals on string-offset access below.
if ( ! is_array( $data ) ) {
$data = array();
}

$plan_name = isset( $data['plan'] ) ? $data['plan'] : '';
$requests = isset( $data['requests'] ) ? $data['requests'] : 0;

$struct['element'] = 'div';
$struct['attributes']['class'][] = 'cld-plan';

$struct['children']['plan'] = $this->make_item( __( 'Plan', 'cloudinary' ), $data['plan'], $this->dir_url . 'css/images/star.svg' );
$struct['children']['plan'] = $this->make_item( __( 'Plan', 'cloudinary' ), $plan_name, $this->dir_url . 'css/images/star.svg' );

if ( $connection->get_usage_stat( 'credits', 'limit' ) ) {
$struct = $this->plan_credit( $struct, $connection );
} else {
$struct = $this->plan_classic( $struct, $connection );
}

$struct['children']['requests'] = $this->make_item( __( 'Total Requests', 'cloudinary' ), number_format_i18n( $data['requests'] ), $this->dir_url . 'css/images/requests.svg' );
$struct['children']['requests'] = $this->make_item( __( 'Total Requests', 'cloudinary' ), number_format_i18n( $requests ), $this->dir_url . 'css/images/requests.svg' );
$struct['children']['assets'] = $this->make_item( __( 'Optimized assets', 'cloudinary' ), number_format_i18n( Sync_Queue::get_optimized_assets() ), $this->dir_url . 'css/images/image.svg' );

return $struct;
Expand Down
5 changes: 4 additions & 1 deletion ui-definitions/settings-sidebar.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@
$plugin = get_plugin_instance();
$data = $plugin->settings->get_value( 'last_usage' );
$cloud_name = $plugin->components['connect']->get_cloud_name();
// `last_usage` may be a string when no successful usage API
// response has been recorded yet; fall back to an empty plan name.
$plan_name = is_array( $data ) && isset( $data['plan'] ) ? $data['plan'] : '';

ob_start();
?>
<?php echo esc_html( $data['plan'] ); ?>
<?php echo esc_html( $plan_name ); ?>
<br />
<span class="cld-ui-description-cloudname cloudname">@<?php echo esc_html( $cloud_name ); ?></span>
<?php
Expand Down