| @@ -27,8 +27,14 @@ | ||
| 27 | 27 | * @param int $optimization_level The optimization level. |
| 28 | 28 | * @return array A list of unoptimized media IDs. |
| 29 | 29 | */ |
| 30 | 30 | public function get_unoptimized_media_ids( $optimization_level ) { |
| 31 | + // @codeCoverageIgnoreStart — requires live NGG POPE classes and DB; not available in unit tests. | |
| 32 | + if ( ! imagify_ngg_has_pope_storage() || ! DB::get_instance()->can_operate() ) { | |
| 33 | + return []; | |
| 34 | + } | |
| 35 | + // @codeCoverageIgnoreEnd | |
| 36 | + | |
| 31 | 37 | global $wpdb; |
| 32 | 38 | |
| 33 | 39 | $this->set_no_time_limit(); |
| 34 | 40 | |
| @@ -102,8 +108,19 @@ | ||
| 102 | 108 | return $data; |
| 103 | 109 | } |
| 104 | 110 | |
| 105 | 111 | /** |
| 112 | + * Get all optimized media ids that can be restored. | |
| 113 | + * | |
| 114 | + * @since 2.3 | |
| 115 | + * | |
| 116 | + * @return array A list of optimized media IDs with backup files available. | |
| 117 | + */ | |
| 118 | + public function get_optimized_media_ids(): array { | |
| 119 | + return []; | |
| 120 | + } | |
| 121 | + | |
| 122 | + /** | |
| 106 | 123 | * Get ids of all optimized media without next-gen versions. |
| 107 | 124 | * |
| 108 | 125 | * @since 2.2 |
| 109 | 126 | * |
| @@ -117,8 +134,20 @@ | ||
| 117 | 134 | * } |
| 118 | 135 | * } |
| 119 | 136 | */ |
| 120 | 137 | public function get_optimized_media_ids_without_format( $format ) { |
| 138 | + // @codeCoverageIgnoreStart — requires live NGG POPE classes and DB; not available in unit tests. | |
| 139 | + if ( ! imagify_ngg_has_pope_storage() || ! DB::get_instance()->can_operate() ) { | |
| 140 | + return [ | |
| 141 | + 'ids' => [], | |
| 142 | + 'errors' => [ | |
| 143 | + 'no_file_path' => [], | |
| 144 | + 'no_backup' => [], | |
| 145 | + ], | |
| 146 | + ]; | |
| 147 | + } | |
| 148 | + // @codeCoverageIgnoreEnd | |
| 149 | + | |
| 121 | 150 | global $wpdb; |
| 122 | 151 | |
| 123 | 152 | $this->set_no_time_limit(); |
| 124 | 153 | |
| @@ -140,10 +169,20 @@ | ||
| 140 | 169 | ON ( ngg.pid = data.pid ) |
| 141 | 170 | WHERE |
| 142 | 171 | ( data.status = 'success' OR data.status = 'already_optimized' ) |
| 143 | 172 | AND data.data NOT LIKE %s |
| 173 | + AND data.data NOT LIKE %s | |
| 144 | 174 | ORDER BY ngg.pid DESC", |
| 145 | - '%' . $wpdb->esc_like( $suffix . '";a:4:{s:7:"success";b:1;' ) . '%' | |
| 175 | + '%' . $wpdb->esc_like( $suffix . '";a:4:{s:7:"success";b:1;' ) . '%', | |
| 176 | + /** | |
| 177 | + * Second predicate: skip images the API permanently refused to convert (the next-gen file | |
| 178 | + * would be heavier than the original, or the file is already compressed). Those are stored | |
| 179 | + * as `<size><suffix>";a:3:{s:15:"permanent_error";b:1;s:7:"success";b:0;s:5:"error";…`. | |
| 180 | + * Transient failures serialize as a 2-element array without the `permanent_error` key, so | |
| 181 | + * they keep being retried. Matching serialized data with LIKE is fragile: the key order | |
| 182 | + * written in Imagify\NGG\Optimization\Data\NGG must not change. | |
| 183 | + */ | |
| 184 | + '%' . $wpdb->esc_like( $suffix . '";a:3:{s:15:"permanent_error";b:1;' ) . '%' | |
| 146 | 185 | ) |
| 147 | 186 | ); |
| 148 | 187 | |
| 149 | 188 | $wpdb->flush(); |
| @@ -192,8 +231,14 @@ | ||
| 192 | 231 | * |
| 193 | 232 | * @return int The number of media. |
| 194 | 233 | */ |
| 195 | 234 | public function has_optimized_media_without_nextgen() { |
| 235 | + // @codeCoverageIgnoreStart — requires live NGG DB table; not available in unit tests. | |
| 236 | + if ( ! DB::get_instance()->can_operate() ) { | |
| 237 | + return 0; | |
| 238 | + } | |
| 239 | + // @codeCoverageIgnoreEnd | |
| 240 | + | |
| 196 | 241 | global $wpdb; |
| 197 | 242 | |
| 198 | 243 | $ngg_table = $wpdb->prefix . 'ngg_pictures'; |
| 199 | 244 | $data_table = DB::get_instance()->get_table_name(); |