PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.8.23.5
Pods – Custom Content Types and Fields v2.8.23.5
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / tribe-common / src / Tribe / Feature_Detection.php
pods / tribe-common / src / Tribe Last commit date
Admin 1 week ago Ajax 1 week ago Asset 1 week ago Context 1 week ago Customizer 1 week ago Debug_Bar 1 week ago Dialog 1 week ago Documentation 1 week ago Duplicate 1 week ago Editor 1 week ago Image 1 week ago JSON_LD 1 week ago Languages 1 week ago Log 1 week ago Meta 1 week ago Models 1 week ago PUE 1 week ago Process 1 week ago Promoter 1 week ago REST 1 week ago Repository 1 week ago Service_Providers 1 week ago Shortcode 1 week ago Support 1 week ago Tabbed_View 1 week ago Tooltip 1 week ago Traits 1 week ago Utils 1 week ago Validator 1 week ago Widget 1 week ago Abstract_Deactivation.php 1 week ago Abstract_Plugin_Register.php 1 week ago App_Shop.php 1 week ago Assets.php 1 week ago Assets_Pipeline.php 1 week ago Autoloader.php 1 week ago Cache.php 1 week ago Cache_Listener.php 1 week ago Changelog_Reader.php 1 week ago Container.php 1 week ago Context.php 1 week ago Cost_Utils.php 1 week ago Credits.php 1 week ago Customizer.php 1 week ago DB_Lock.php 1 week ago Data.php 1 week ago Date_Utils.php 1 week ago Db.php 1 week ago Debug.php 1 week ago Dependency.php 1 week ago Deprecation.php 1 week ago Editor.php 1 week ago Error.php 1 week ago Exception.php 1 week ago Extension.php 1 week ago Extension_Loader.php 1 week ago Feature_Detection.php 1 week ago Field.php 1 week ago Field_Conditional.php 1 week ago Freemius.php 1 week ago Log.php 1 week ago Main.php 1 week ago Notices.php 1 week ago Plugin_Meta_Links.php 1 week ago Plugins.php 1 week ago Plugins_API.php 1 week ago Post_History.php 1 week ago Post_Transient.php 1 week ago Promise.php 1 week ago Repository.php 1 week ago Rewrite.php 1 week ago Settings.php 1 week ago Settings_Manager.php 1 week ago Settings_Tab.php 1 week ago Simple_Table.php 1 week ago Support.php 1 week ago Tabbed_View.php 1 week ago Template.php 1 week ago Template_Factory.php 1 week ago Template_Part_Cache.php 1 week ago Templates.php 1 week ago Terms.php 1 week ago Timezones.php 1 week ago Tracker.php 1 week ago Updater.php 1 week ago Validate.php 1 week ago View_Helpers.php 1 week ago
Feature_Detection.php
259 lines
1 <?php
2 /**
3 * An abstraction layer to handle feature detection queries the plugin components
4 * might need.
5 *
6 * @since 4.7.23
7 */
8
9 use Tribe__Utils__Array as Arr;
10
11 /**
12 * Class Tribe__Feature_Detection
13 *
14 * @since 4.7.23
15 */
16 class Tribe__Feature_Detection {
17
18 /**
19 * The name of the transient storing the support check results.
20 *
21 * @var string
22 */
23 public static $transient = 'tribe_feature_detection';
24
25 /**
26 * A set of example byte sizes of result sets.
27 *
28 * @since 4.10.2
29 *
30 * @var array
31 */
32 public static $example_size = [
33 'post_result' => 6000,
34 ];
35
36 /**
37 * The name of the option that will be used to indicate a feature detection is running.
38 *
39 * @var string
40 */
41 protected $lock_option_name;
42
43 /**
44 * Checks whether async, AJAX-based, background processing is supported or not.
45 *
46 * To avoid making this costly check on each load the result of this check is cached
47 * in the `tribe_feature_detection` transient, under the `supports_async_process` key.
48 *
49 * @since 4.7.23
50 *
51 * @param bool $force Whether to use the cache value, if available, or force the check
52 * to be made again.
53 *
54 * @return bool Whether async, AJAX-based, background processing is supported or not.
55 */
56 public function supports_async_process( $force = false ) {
57 /**
58 * Filters whether async, AJAX-based, processing is supported or not.
59 *
60 * Returning a non `null` value here will make this method bail and
61 * return the filtered value immediately.
62 *
63 * @since 4.7.23
64 *
65 * @param bool $supports_async_process Whether async, AJAX-based, processing is supported or not.
66 * @param bool $force Whether the check is forcing the cached value to be refreshed
67 * or not.
68 */
69 $supports_async_process = apply_filters( 'tribe_supports_async_process', null, $force );
70 if ( null !== $supports_async_process ) {
71 return (bool) $supports_async_process;
72 }
73
74 $cached = get_transient( self::$transient );
75
76 $this->lock_option_name = 'tribe_feature_support_check_lock';
77 if (
78 $force
79 || false === $cached
80 || ( is_array( $cached ) && ! isset( $cached['supports_async_process'] ) )
81 ) {
82 if ( $this->is_locked() ) {
83 // We're already running this check, bail and return the safe option for the time being.
84 return false;
85 }
86
87 // Let's avoid race conditions by running two or more checks at the same time.
88 $this->lock();
89
90 // Log that we're checking for AJAX-based async process support using the tester.
91 tribe( 'logger' )->log( 'Checking for AJAX-based async processing support triggering a test request.', Tribe__Log::DEBUG );
92
93 /*
94 * Build and dispatch the tester: if it works a transient should be set.
95 */
96 $tester = new Tribe__Process__Tester();
97 tribe( 'logger' )->log( 'Dispatching AJAX-based async processing support test request.', Tribe__Log::DEBUG );
98 $tester->dispatch();
99
100 $wait_up_to = 10;
101 $start = time();
102 $supports_async_process = false;
103 $transient_name = Tribe__Process__Tester::TRANSIENT_NAME;
104
105 while ( time() <= $start + $wait_up_to ) {
106 // We want to force a refetch from the database on each check.
107 wp_cache_delete( $transient_name, 'transient' );
108 $supports_async_process = (bool) get_transient( $transient_name );
109
110 if ( $supports_async_process ) {
111 break;
112 }
113 sleep( $wait_up_to / 5 );
114 }
115
116 // Remove it not to spoof future checks.
117 delete_transient( $transient_name );
118
119 $this->unlock();
120
121 $cached['supports_async_process'] = $supports_async_process;
122
123 if ( $supports_async_process ) {
124 tribe( 'logger' )->log( 'AJAX-based async processing is supported.', Tribe__Log::DEBUG );
125 } else {
126 tribe( 'logger' )->log( 'AJAX-based async processing is not supported; background processing will rely on WP Cron.', Tribe__Log::DEBUG );
127 }
128
129 set_transient( self::$transient, $cached, WEEK_IN_SECONDS );
130 }
131
132 return $cached['supports_async_process'];
133 }
134
135 /**
136 * Sets the lock option to `1` to indicate a feature detection is running.
137 *
138 * @since 4.8.1
139 */
140 protected function lock() {
141 update_option( $this->lock_option_name, '1' );
142 }
143
144 /**
145 * Deletes the lock option to indicate the current feature detection process is done.
146 *
147 * @since 4.8.1
148 */
149 protected function unlock() {
150 delete_option( $this->lock_option_name );
151 }
152
153 /**
154 * Checks whether a feature detection lock is currently in place or not.
155 *
156 * @since 4.8.1
157 *
158 * @return bool Whether a feature detection lock is currently in place or not.
159 */
160 protected function is_locked() {
161 $lock_option = get_option( $this->lock_option_name );
162
163 return ! empty( $lock_option );
164 }
165
166 /**
167 * Returns the value of the `max_allowed_packet` MYSQL variable, if set, or a default value.
168 *
169 * @since 4.10.2
170 *
171 * @return int The byte size of the `max_allowed_packet` MYSQL variable.
172 */
173 public function get_mysql_max_packet_size() {
174 /**
175 * Filters the value of the `max_allowed_packet` variable before it's read from the database.
176 *
177 * If the value returned from this filter is not `null`, then it will be assumed to be the value.
178 *
179 * @since 4.10.2
180 *
181 * @param int $mysql_max_packet_size The value of the `max_allowed_packet` variable, initially `null`.
182 */
183 $mysql_max_packet_size = apply_filters( 'tribe_max_allowed_packet_size', null );
184
185 if ( null !== $mysql_max_packet_size ) {
186 return absint( $mysql_max_packet_size );
187 }
188
189 /** @var Tribe__Cache $cache */
190 $cache = tribe( 'cache' );
191
192 $cached = $cache->get( 'max_allowed_packet' );
193
194 if ( false !== $cached ) {
195 return $cached;
196 }
197
198 global $wpdb;
199 $mysql_max_packet_size = $wpdb->get_var( "SHOW VARIABLES LIKE 'max_allowed_packet'", 1 );
200 // At min set it to 2 MBs.
201 $mysql_max_packet_size = absint( max( absint( $mysql_max_packet_size ), 2097152 ) );
202
203 $cache->set( 'max_allowed_packet', $mysql_max_packet_size, WEEK_IN_SECONDS );
204
205 return $mysql_max_packet_size;
206 }
207
208 /**
209 * Returns the suggested SQL LIMIT value, based on the `max_allowed_packet` size and example string length.
210 *
211 * This is useful to size "reasonable" LIMITs when dealing with either very long queries or potentially long
212 * result sets.
213 *
214 * @since 4.10.2
215 *
216 * @param string $example_string The example string.
217 *
218 * @return int The suggested LIMIT value.
219 */
220 public function mysql_limit_for_string( $example_string ) {
221 $byte_size = function_exists( 'mb_strlen' )
222 ? mb_strlen( $example_string )
223 : strlen( $example_string );
224
225 return $this->mysql_limit_for_size( $byte_size );
226 }
227
228 /**
229 * Returns the SQL LIMIT for a byte size, in relation to the `max_allowed_packet` value.
230 *
231 * @since 4.10.2
232 *
233 * @param int $byte_size The byte size to check.
234 *
235 * @return int The SQL LIMIT value.
236 */
237 public function mysql_limit_for_size( $byte_size ) {
238 return absint( floor( $this->get_mysql_max_packet_size() / $byte_size ) * 0.8 );
239 }
240
241 /**
242 * Provides the SQL LIMIT value, in relation to the `max_allowed_packet` value, for a pre-existing example.
243 *
244 * Defaults to the complete post result example string if the example is not found.
245 *
246 * @since 4.10.2
247 *
248 * @param string $example The name of the example to return. See the `Tribe__Feature_Detection::$example_sizes`
249 * prop for the available examples. Defaults to the `post_result` one.
250 *
251 * @return int The SQL LIMIT value for the example.
252 */
253 public function mysql_limit_for_example( $example ) {
254 $example_size = Arr::get( static::$example_size, $example, static::$example_size['post_result'] );
255
256 return $this->mysql_limit_for_size( $example_size );
257 }
258 }
259