PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
← All changes | classes/Job/MediaOptimization.php +130 -0 2.3.0 → trunk View file →
@@ -13,8 +13,18 @@
13 13 final class MediaOptimization extends \Imagify_Abstract_Background_Process {
14 14 use InstanceGetterTrait;
15 15
16 16 /**
17 + * Batch-key segment used to mark a batch as "urgent" (high priority).
18 + * Shared by generate_key() (write path) and get_batches() (read path) so both
19 + * always agree on the exact same string shape.
20 + *
21 + * @var string
22 + * @since 2.3.2
23 + */
24 + private const URGENT_KEY_SEGMENT = 'batch_urgent';
25 +
26 + /**
17 27 * Background process: the action to perform.
18 28 *
19 29 * @var string
20 30 * @since 1.9
@@ -48,8 +58,9 @@
48 58 * It should contain the following though:
49 59 *
50 60 * @type string $hook_suffix Suffix used to trigger hooks before and after optimization. Should be always provided.
51 61 * @type bool $delete_backup True to delete the backup file after the optimization process. This is used when a temporary backup of the original file has been created, but backup option is disabled. Default is false.
62 + * @type bool $bulk True when this optimization was triggered by a bulk run (see Bulk::force_optimize()). Forwarded verbatim to the 'imagify_before_*'/'imagify_after_*' hook callbacks below. Default is false.
52 63 * }
53 64 * }
54 65 * @return array|bool The modified item to put back in the queue. False to remove the item from the queue.
55 66 */
@@ -72,8 +83,127 @@
72 83
73 84 // End of the queue.
74 85 $this->optimization_process->unlock();
75 86 return false;
87 + }
88 +
89 + /**
90 + * Generate the batch key.
91 + * Overrides the vendored method to give priority ("urgent") batches a distinct
92 + * key shape, so get_batches() can order them first.
93 + *
94 + * @since 2.3.2
95 + *
96 + * @param int $length Optional, length of the string to return. Default 64.
97 + * @param string $key Optional, string with a prefix key. Default 'batch'.
98 + * @return string
99 + */
100 + protected function generate_key( $length = 64, $key = 'batch' ) {
101 + if ( 'batch' === $key && $this->has_priority_item_queued() ) {
102 + return parent::generate_key( $length, self::URGENT_KEY_SEGMENT );
103 + }
104 +
105 + return parent::generate_key( $length, $key );
106 + }
107 +
108 + /**
109 + * Tell if any of the not-yet-persisted queued items carries a truthy 'priority' key.
110 + *
111 + * A single truthy item marks the whole batch urgent, which only makes sense because
112 + * a batch is always a singleton at this point: generate_key() is called from
113 + * push_to_queue(), immediately followed by save(), one item at a time. If several
114 + * items were ever pushed to $this->data before save() is called, they would all end
115 + * up sharing the same "urgent" key as soon as one of them requests priority.
116 + *
117 + * @since 2.3.2
118 + *
119 + * @return bool
120 + */
121 + private function has_priority_item_queued(): bool {
122 + if ( empty( $this->data ) || ! is_array( $this->data ) ) {
123 + return false;
124 + }
125 +
126 + foreach ( $this->data as $item ) {
127 + if ( is_array( $item ) && ! empty( $item['priority'] ) ) {
128 + return true;
129 + }
130 + }
131 +
132 + return false;
133 + }
134 +
135 + /**
136 + * Get batches.
137 + * Overrides the vendored method to return "urgent" (priority) batches before
138 + * normal ones, each tier still ordered FIFO (by option/meta ID) internally.
139 + *
140 + * @since 2.3.2
141 + *
142 + * @param int $limit Number of batches to return, defaults to all.
143 + * @return array of stdClass
144 + */
145 + public function get_batches( $limit = 0 ) {
146 + global $wpdb;
147 +
148 + if ( empty( $limit ) || ! is_int( $limit ) ) {
149 + $limit = 0;
150 + }
151 +
152 + $table = $wpdb->options;
153 + $column = 'option_name';
154 + $key_column = 'option_id';
155 + $value_column = 'option_value';
156 +
157 + if ( is_multisite() ) {
158 + $table = $wpdb->sitemeta;
159 + $column = 'meta_key';
160 + $key_column = 'meta_id';
161 + $value_column = 'meta_value';
162 + }
163 +
164 + $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
165 + $urgent_key = $wpdb->esc_like( $this->identifier . '_' . self::URGENT_KEY_SEGMENT . '_' ) . '%';
166 +
167 + $sql = '
168 + SELECT *
169 + FROM ' . $table . '
170 + WHERE ' . $column . ' LIKE %s
171 + ORDER BY ( ' . $column . ' LIKE %s ) DESC, ' . $key_column . ' ASC
172 + ';
173 +
174 + $args = [ $key, $urgent_key ];
175 +
176 + if ( ! empty( $limit ) ) {
177 + $sql .= ' LIMIT %d';
178 + $args[] = $limit;
179 + }
180 +
181 + $items = $wpdb->get_results(
182 + $wpdb->prepare(
183 + $sql, // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
184 + $args
185 + )
186 + );
187 +
188 + $batches = [];
189 +
190 + if ( ! empty( $items ) ) {
191 + $allowed_classes = $this->allowed_batch_data_classes;
192 +
193 + $batches = array_map(
194 + static function ( $item ) use ( $column, $value_column, $allowed_classes ) {
195 + $batch = new \stdClass();
196 + $batch->key = $item->{$column};
197 + $batch->data = static::maybe_unserialize( $item->{$value_column}, $allowed_classes );
198 +
199 + return $batch;
200 + },
201 + $items
202 + );
203 + }
204 +
205 + return $batches;
76 206 }
77 207
78 208 /**
79 209 * Trigger hooks before the optimization job.