@@ -375,49 +375,101 @@ protected function get_query_actions_sql( array $query, $select_or_count = 'sele
375375 throw new InvalidArgumentException ( __ ( 'Invalid value for select or count parameter. Cannot query actions. ' , 'action-scheduler ' ) );
376376 }
377377
378- $ query = wp_parse_args (
379- $ query ,
380- array (
381- 'hook ' => '' ,
382- 'args ' => null ,
383- 'date ' => null ,
384- 'date_compare ' => '<= ' ,
385- 'modified ' => null ,
386- 'modified_compare ' => '<= ' ,
387- 'group ' => '' ,
388- 'status ' => '' ,
389- 'claimed ' => null ,
390- 'per_page ' => 5 ,
391- 'offset ' => 0 ,
392- 'orderby ' => 'date ' ,
393- 'order ' => 'ASC ' ,
394- )
395- );
378+ $ query = wp_parse_args ( $ query , array (
379+ 'hook ' => '' ,
380+ 'args ' => null ,
381+ 'partial_args_matching ' => 'off ' , // can be 'like' or 'json'
382+ 'date ' => null ,
383+ 'date_compare ' => '<= ' ,
384+ 'modified ' => null ,
385+ 'modified_compare ' => '<= ' ,
386+ 'group ' => '' ,
387+ 'status ' => '' ,
388+ 'claimed ' => null ,
389+ 'per_page ' => 5 ,
390+ 'offset ' => 0 ,
391+ 'orderby ' => 'date ' ,
392+ 'order ' => 'ASC ' ,
393+ ) );
396394
397395 /** @var \wpdb $wpdb */
398396 global $ wpdb ;
397+
398+ $ db_server_info = is_callable ( array ( $ wpdb , 'db_server_info ' ) ) ? $ wpdb ->db_server_info () : $ wpdb ->db_version ();
399+ if ( false !== strpos ( $ db_server_info , 'MariaDB ' ) ) {
400+ $ supports_json = version_compare (
401+ PHP_VERSION_ID >= 80016 ? $ wpdb ->db_version () : preg_replace ( '/[^0-9.].*/ ' , '' , str_replace ( '5.5.5- ' , '' , $ db_server_info ) ),
402+ '10.2 ' ,
403+ '>= '
404+ );
405+ } else {
406+ $ supports_json = version_compare ( $ wpdb ->db_version (), '5.7 ' , '>= ' );
407+ }
408+
399409 $ sql = ( 'count ' === $ select_or_count ) ? 'SELECT count(a.action_id) ' : 'SELECT a.action_id ' ;
400- $ sql .= " FROM {$ wpdb ->actionscheduler_actions } a " ;
410+ $ sql .= " FROM {$ wpdb ->actionscheduler_actions } a " ;
401411 $ sql_params = array ();
402412
403413 if ( ! empty ( $ query ['group ' ] ) || 'group ' === $ query ['orderby ' ] ) {
404414 $ sql .= " LEFT JOIN {$ wpdb ->actionscheduler_groups } g ON g.group_id=a.group_id " ;
405415 }
406416
407- $ sql .= ' WHERE 1=1 ' ;
417+ $ sql .= " WHERE 1=1 " ;
408418
409419 if ( ! empty ( $ query ['group ' ] ) ) {
410- $ sql .= ' AND g.slug=%s ' ;
420+ $ sql .= " AND g.slug=%s " ;
411421 $ sql_params [] = $ query ['group ' ];
412422 }
413423
414- if ( $ query ['hook ' ] ) {
415- $ sql .= ' AND a.hook=%s ' ;
424+ if ( ! empty ( $ query ['hook ' ] ) ) {
425+ $ sql .= " AND a.hook=%s " ;
416426 $ sql_params [] = $ query ['hook ' ];
417427 }
428+
418429 if ( ! is_null ( $ query ['args ' ] ) ) {
419- $ sql .= ' AND a.args=%s ' ;
420- $ sql_params [] = $ this ->get_args_for_query ( $ query ['args ' ] );
430+ switch ( $ query ['partial_args_matching ' ] ) {
431+ case 'json ' :
432+ if ( ! $ supports_json ) {
433+ throw new \RuntimeException ( __ ( 'JSON partial matching not supported in your environment. Please check your MySQL/MariaDB version. ' , 'action-scheduler ' ) );
434+ }
435+ $ supported_types = array (
436+ 'integer ' => '%d ' ,
437+ 'boolean ' => '%s ' ,
438+ 'double ' => '%f ' ,
439+ 'string ' => '%s ' ,
440+ );
441+ foreach ( $ query ['args ' ] as $ key => $ value ) {
442+ $ value_type = gettype ( $ value );
443+ if ( 'boolean ' === $ value_type ) {
444+ $ value = $ value ? 'true ' : 'false ' ;
445+ }
446+ $ placeholder = isset ( $ supported_types [ $ value_type ] ) ? $ supported_types [ $ value_type ] : false ;
447+ if ( ! $ placeholder ) {
448+ throw new \RuntimeException ( sprintf (
449+ /* translators: %s: provided value type */
450+ __ ( 'The value type for the JSON partial matching is not supported. Must be either integer, boolean, double or string. %s type provided. ' , 'action-scheduler ' ),
451+ $ value_type
452+ ) );
453+ }
454+ $ sql .= ' AND JSON_EXTRACT(a.args, %s)= ' .$ placeholder ;
455+ $ sql_params [] = '$. ' .$ key ;
456+ $ sql_params [] = $ value ;
457+ }
458+ break ;
459+ case 'like ' :
460+ foreach ( $ query ['args ' ] as $ key => $ value ) {
461+ $ sql .= ' AND a.args LIKE %s ' ;
462+ $ json_partial = $ wpdb ->esc_like ( trim ( json_encode ( array ( $ key => $ value ) ), '{} ' ) );
463+ $ sql_params [] = "% {$ json_partial }% " ;
464+ }
465+ break ;
466+ case 'off ' :
467+ $ sql .= " AND a.args=%s " ;
468+ $ sql_params [] = $ this ->get_args_for_query ( $ query ['args ' ] );
469+ break ;
470+ default :
471+ throw new \RuntimeException ( __ ( 'Unknown partial args matching value. ' , 'action-scheduler ' ) );
472+ }
421473 }
422474
423475 if ( $ query ['status ' ] ) {
@@ -778,7 +830,7 @@ protected function claim_actions( $claim_id, $limit, \DateTime $before_date = nu
778830
779831 if ( ! empty ( $ hooks ) ) {
780832 $ placeholders = array_fill ( 0 , count ( $ hooks ), '%s ' );
781- $ where .= ' AND hook IN ( ' . join ( ', ' , $ placeholders ) . ') ' ;
833+ $ where .= ' AND hook IN ( ' . join ( ', ' , $ placeholders ) . ') ' ;
782834 $ params = array_merge ( $ params , array_values ( $ hooks ) );
783835 }
784836
@@ -792,7 +844,7 @@ protected function claim_actions( $claim_id, $limit, \DateTime $before_date = nu
792844 throw new InvalidArgumentException ( sprintf ( __ ( 'The group "%s" does not exist. ' , 'action-scheduler ' ), $ group ) );
793845 }
794846
795- $ where .= ' AND group_id = %d ' ;
847+ $ where .= ' AND group_id = %d ' ;
796848 $ params [] = $ group_id ;
797849 }
798850
0 commit comments