@@ -14,7 +14,7 @@ $sql = $wpdb->prepare( 'SELECT * FROM `table` WHERE id = ' . $id ); // OK - this
1414$ sql = $ wpdb ->prepare ( "SELECT * FROM `table` WHERE id = $ id " ); // OK - this will be handled by the PreparedSQL sniff.
1515$ sql = $ wpdb ->prepare ( "SELECT * FROM `table` WHERE id = {$ id ['some%sing ' ]}" ); // OK - this will be handled by the PreparedSQL sniff.
1616$ sql = $ wpdb ?->prepare( 'SELECT * FROM ' . $ wpdb ->users ); // Warning.
17- $ sql = $ wpdb ->prepare ( "SELECT * FROM ` {$ wpdb ->users }` " ); // Warning.
17+ $ sql = $ wpdb ->PREPARE ( "SELECT * FROM ` {$ wpdb ->users }` " ); // Warning.
1818$ sql = $ wpdb ->prepare ( "SELECT * FROM ` {$ wpdb ->users }` WHERE id = $ id " ); // OK - this will be handled by the PreparedSQL sniff.
1919
2020/*
@@ -80,7 +80,7 @@ $where = $wpdb->prepare(
8080); // OK.
8181
8282$ where = $ wpdb ->prepare (
83- sprintf (
83+ \ sprintf (
8484 "{$ wpdb ->posts }.post_type IN (%s)
8585 AND {$ wpdb ->posts }.post_status IN (%s) " ,
8686 implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ), ),
@@ -99,7 +99,7 @@ $where = $wpdb->prepare(
9999); // OK.
100100
101101$ query = $ wpdb ->prepare (
102- sprintf (
102+ Sprintf (
103103 'SELECT COUNT(ID)
104104 FROM `%s`
105105 WHERE ID IN (%s)
@@ -124,7 +124,7 @@ $results = $wpdb->get_results(
124124); // OK.
125125
126126$ query = $ wpdb ->prepare (
127- sprintf (
127+ \ SPRINTF (
128128 'SELECT COUNT(ID)
129129 FROM `%s`
130130 WHERE ID in (%s)
@@ -382,7 +382,7 @@ $where = $wpdb->prepare(
382382$ where = $ wpdb ->prepare (
383383 sprintf (
384384 "{$ wpdb ->posts }.post_type IN (%s) " ,
385- \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
385+ \ImplodE ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
386386 ),
387387 $ post_types
388388); // OK.
@@ -397,7 +397,7 @@ $where = $wpdb->prepare(
397397
398398$ where = $ wpdb ->prepare (
399399 "{$ wpdb ->posts }.post_type IN ( "
400- . implode ( ', ' , \array_fill ( 0 , count ($ post_types ), '%s ' ) )
400+ . implode ( ', ' , \Array_Fill ( 0 , count ($ post_types ), '%s ' ) )
401401 . ") AND {$ wpdb ->posts }.post_status IN ( "
402402 . implode ( ', ' , \array_fill ( 0 , count ($ post_statusses ), '%s ' ) )
403403 . ') ' ,
@@ -518,3 +518,295 @@ $where = $wpdb->prepare(
518518 */
519519$ callback = $ wpdb ->prepare (...); // OK.
520520
521+ /*
522+ * Safeguard correct handling of all types of namespaced calls to the wpdb::prepare() method.
523+ *
524+ * Note that calling wpdb::prepare() statically will result in an error. Still, the tests are included here since the
525+ * sniff handles those calls.
526+ *
527+ * Except for the fully qualified global calls, the calls below are currently false positives. The sniff
528+ * incorrectly identifies calls to a non-global class named `wpdb` preceded by a namespace separator as calls to the
529+ * global `$wpdb` object. Related to: https://github.com/WordPress/WordPress-Coding-Standards/issues/2710.
530+ */
531+ $ sql = \wpdb::prepare ( "SELECT * FROM $ wpdb ->users WHERE id = %d AND user_login = %s " );
532+ $ sql = \WPDB ::prepare ( "SELECT * FROM $ wpdb ->users WHERE id = %d AND user_login = %s " );
533+ $ sql = MyNamespace \wpdb::prepare ( "SELECT * FROM $ wpdb ->users WHERE id = %d AND user_login = %s " );
534+ $ sql = \MyNamespace \wpdb::prepare ( "SELECT * FROM $ wpdb ->users WHERE id = %d AND user_login = %s " );
535+ $ sql = namespace \wpdb::prepare ( "SELECT * FROM $ wpdb ->users WHERE id = %d AND user_login = %s " ); // The sniff should start flagging this once it can resolve relative namespaces.
536+ $ sql = namespace \Sub \wpdb::prepare ( "SELECT * FROM $ wpdb ->users WHERE id = %d AND user_login = %s " );
537+
538+ /*
539+ * Safeguard correct handling of namespaced implode() calls when nested as a parameter to sprintf() (except fully
540+ * qualified calls to the global implode() function, which is already handled above).
541+ */
542+ $ where = $ wpdb ->prepare (
543+ sprintf (
544+ "{$ wpdb ->posts }.post_type IN (%s) " ,
545+ MyNamespace \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
546+ ),
547+ $ post_types
548+ );
549+ $ where = $ wpdb ->prepare (
550+ sprintf (
551+ "{$ wpdb ->posts }.post_type IN (%s) " ,
552+ \MyNamespace \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
553+ ),
554+ $ post_types
555+ );
556+ $ where = $ wpdb ->prepare ( // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
557+ sprintf (
558+ "{$ wpdb ->posts }.post_type IN (%s) " ,
559+ namespace \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
560+ ),
561+ $ post_types
562+ );
563+ $ where = $ wpdb ->prepare (
564+ sprintf (
565+ "{$ wpdb ->posts }.post_type IN (%s) " ,
566+ namespace \Sub \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
567+ ),
568+ $ post_types
569+ );
570+
571+ /*
572+ * Safeguard correct handling of namespaced array_fill() calls when nested inside sprintf() (except fully qualified
573+ * calls to the global array_fill() function, which is already handled above).
574+ */
575+ $ where = $ wpdb ->prepare (
576+ sprintf (
577+ "{$ wpdb ->posts }.post_type IN (%s) " ,
578+ implode ( ', ' , MyNamespace \array_fill ( 0 , count ($ post_types ), '%s ' ) )
579+ ),
580+ $ post_types
581+ );
582+ $ where = $ wpdb ->prepare (
583+ sprintf (
584+ "{$ wpdb ->posts }.post_type IN (%s) " ,
585+ implode ( ', ' , \MyNamespace \array_fill ( 0 , count ($ post_types ), '%s ' ) )
586+ ),
587+ $ post_types
588+ );
589+ $ where = $ wpdb ->prepare ( // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
590+ sprintf (
591+ "{$ wpdb ->posts }.post_type IN (%s) " ,
592+ implode ( ', ' , namespace \array_fill ( 0 , count ($ post_types ), '%s ' ) )
593+ ),
594+ $ post_types
595+ );
596+ $ where = $ wpdb ->prepare (
597+ sprintf (
598+ "{$ wpdb ->posts }.post_type IN (%s) " ,
599+ implode ( ', ' , namespace \Sub \array_fill ( 0 , count ($ post_types ), '%s ' ) )
600+ ),
601+ $ post_types
602+ );
603+
604+ /*
605+ * Safeguard correct handling of namespaced implode() calls in direct string concatenation (when NOT nested inside
606+ * sprintf()). Fully qualified calls to the global implode() are already handled above.
607+ */
608+ $ where = $ wpdb ->prepare (
609+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
610+ . MyNamespace \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
611+ . ') ' ,
612+ 'publish '
613+ );
614+ $ where = $ wpdb ->prepare (
615+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
616+ . \MyNamespace \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
617+ . ') ' ,
618+ 'publish '
619+ );
620+ $ where = $ wpdb ->prepare ( // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
621+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
622+ . namespace \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
623+ . ') ' ,
624+ 'publish '
625+ );
626+ $ where = $ wpdb ->prepare (
627+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
628+ . namespace \Sub \implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
629+ . ') ' ,
630+ 'publish '
631+ );
632+
633+ /*
634+ * Safeguard correct handling of namespaced array_fill() calls in direct string concatenation (when NOT nested inside
635+ * sprintf()). Fully qualified calls to the global implode() are already handled above.
636+ */
637+ $ where = $ wpdb ->prepare (
638+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
639+ . implode ( ', ' , MyNamespace \array_fill ( 0 , count ($ post_types ), '%s ' ) )
640+ . ') ' ,
641+ 'publish '
642+ );
643+ $ where = $ wpdb ->prepare (
644+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
645+ . implode ( ', ' , \MyNamespace \array_fill ( 0 , count ($ post_types ), '%s ' ) ) . ') ' ,
646+ 'publish '
647+ );
648+ $ where = $ wpdb ->prepare ( // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
649+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
650+ . implode ( ', ' , namespace \array_fill ( 0 , count ($ post_types ), '%s ' ) )
651+ . ') ' ,
652+ 'publish '
653+ );
654+ $ where = $ wpdb ->prepare (
655+ "SELECT * FROM {$ wpdb ->posts } WHERE post_status = %s AND post_type IN ( "
656+ . implode ( ', ' , namespace \Sub \array_fill ( 0 , count ($ post_types ), '%s ' ) )
657+ . ') ' ,
658+ 'publish '
659+ );
660+
661+ /*
662+ * Safeguard correct handling of all types of namespaced calls to sprintf() except fully qualified calls to the
663+ * global sprintf() function, which is already handled above.
664+ *
665+ * The calls below are currently false negatives. The sniff incorrectly treats namespaced sprintf() calls as
666+ * calls to the global sprintf() function and does not flag them.
667+ * See: https://github.com/WordPress/WordPress-Coding-Standards/issues/2720
668+ */
669+ $ where = $ wpdb ->prepare (
670+ MyNamespace \sprintf (
671+ "{$ wpdb ->posts }.post_type IN (%s) " ,
672+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
673+ ),
674+ $ post_types
675+ );
676+ $ where = $ wpdb ->prepare (
677+ \MyNamespace \sprintf (
678+ "{$ wpdb ->posts }.post_type IN (%s) " ,
679+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
680+ ),
681+ $ post_types
682+ );
683+ $ where = $ wpdb ->prepare (
684+ namespace \sprintf ( // This should NOT be flagged in the future once the sniff is able to resolve relative namespaces.
685+ "{$ wpdb ->posts }.post_type IN (%s) " ,
686+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
687+ ),
688+ $ post_types
689+ );
690+ $ where = $ wpdb ->prepare (
691+ namespace \Sub \sprintf (
692+ "{$ wpdb ->posts }.post_type IN (%s) " ,
693+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
694+ ),
695+ $ post_types
696+ );
697+
698+ /*
699+ * Safeguard correct handling of method calls to methods named sprintf(), implode(), or array_fill().
700+ * These should NOT be analyzed as global function calls.
701+ */
702+
703+ // sprintf() method calls. The sprintf() calls below are currently false negatives. The sniff incorrectly treats method
704+ // calls with the same name as global functions as calls to the global functions and does not flag them.
705+ // See: https://github.com/WordPress/WordPress-Coding-Standards/issues/2720
706+ $ where = $ wpdb ->prepare (
707+ $ obj ->sprintf (
708+ "{$ wpdb ->posts }.post_type IN (%s) " ,
709+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
710+ ),
711+ $ post_types
712+ );
713+ $ where = $ wpdb ->prepare (
714+ $ obj ?->sprintf(
715+ "{$ wpdb ->posts }.post_type IN (%s) " ,
716+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
717+ ),
718+ $ post_types
719+ );
720+ $ where = $ wpdb ->prepare (
721+ MyClass::sprintf (
722+ "{$ wpdb ->posts }.post_type IN (%s) " ,
723+ implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
724+ ),
725+ $ post_types
726+ );
727+
728+ // implode() method calls nested inside sprintf().
729+ $ where = $ wpdb ->prepare (
730+ sprintf (
731+ "{$ wpdb ->posts }.post_type IN (%s) " ,
732+ $ obj ->implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
733+ ),
734+ $ post_types
735+ );
736+ $ where = $ wpdb ->prepare (
737+ sprintf (
738+ "{$ wpdb ->posts }.post_type IN (%s) " ,
739+ $ obj ?->implode( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
740+ ),
741+ $ post_types
742+ );
743+ $ where = $ wpdb ->prepare (
744+ sprintf (
745+ "{$ wpdb ->posts }.post_type IN (%s) " ,
746+ MyClass::implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
747+ ),
748+ $ post_types
749+ );
750+
751+ // implode() method calls in direct string concatenation.
752+ $ where = $ wpdb ->prepare (
753+ "post_status = %s AND post_type IN ( "
754+ . $ obj ->implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
755+ . ') ' ,
756+ 'publish '
757+ );
758+ $ where = $ wpdb ->prepare (
759+ "post_status = %s AND post_type IN ( "
760+ . $ obj ?->implode( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
761+ . ') ' ,
762+ 'publish '
763+ );
764+ $ where = $ wpdb ->prepare (
765+ "post_status = %s AND post_type IN ( "
766+ . MyClass::implode ( ', ' , array_fill ( 0 , count ($ post_types ), '%s ' ) )
767+ . ') ' ,
768+ 'publish '
769+ );
770+
771+ // array_fill() method calls nested inside implode() which is nested inside sprintf().
772+ $ where = $ wpdb ->prepare (
773+ sprintf (
774+ "{$ wpdb ->posts }.post_type IN (%s) " ,
775+ implode ( ', ' , $ obj ->array_fill ( 0 , count ($ post_types ), '%s ' ) )
776+ ),
777+ $ post_types
778+ );
779+ $ where = $ wpdb ->prepare (
780+ sprintf (
781+ "{$ wpdb ->posts }.post_type IN (%s) " ,
782+ implode ( ', ' , $ obj ?->array_fill( 0 , count ($ post_types ), '%s ' ) )
783+ ),
784+ $ post_types
785+ );
786+ $ where = $ wpdb ->prepare (
787+ sprintf (
788+ "{$ wpdb ->posts }.post_type IN (%s) " ,
789+ implode ( ', ' , MyClass::array_fill ( 0 , count ($ post_types ), '%s ' ) )
790+ ),
791+ $ post_types
792+ );
793+
794+ // array_fill() method calls nested inside implode() in direct string concatenation.
795+ $ where = $ wpdb ->prepare (
796+ "post_status = %s AND post_type IN ( "
797+ . implode ( ', ' , $ obj ->array_fill ( 0 , count ($ post_types ), '%s ' ) )
798+ . ') ' ,
799+ 'publish '
800+ );
801+ $ where = $ wpdb ->prepare (
802+ "post_status = %s AND post_type IN ( "
803+ . implode ( ', ' , $ obj ?->array_fill( 0 , count ($ post_types ), '%s ' ) )
804+ . ') ' ,
805+ 'publish '
806+ );
807+ $ where = $ wpdb ->prepare (
808+ "post_status = %s AND post_type IN ( "
809+ . implode ( ', ' , MyClass::array_fill ( 0 , count ($ post_types ), '%s ' ) )
810+ . ') ' ,
811+ 'publish '
812+ );
0 commit comments