1313
1414use PHP_CodeSniffer \Exceptions \RuntimeException ;
1515use PHP_CodeSniffer \Util ;
16+ use stdClass ;
1617
1718class Ruleset
1819{
@@ -960,6 +961,11 @@ private function processRule($rule, $newSniffs, $depth=0)
960961 if (isset ($ rule ->properties ) === true
961962 && $ this ->shouldProcessElement ($ rule ->properties ) === true
962963 ) {
964+ $ propertyScope = 'standard ' ;
965+ if ($ code === $ ref || substr ($ ref , -9 ) === 'Sniff.php ' ) {
966+ $ propertyScope = 'sniff ' ;
967+ }
968+
963969 foreach ($ rule ->properties ->property as $ prop ) {
964970 if ($ this ->shouldProcessElement ($ prop ) === false ) {
965971 continue ;
@@ -980,9 +986,9 @@ private function processRule($rule, $newSniffs, $depth=0)
980986 $ values = [];
981987 if (isset ($ prop ['extend ' ]) === true
982988 && (string ) $ prop ['extend ' ] === 'true '
983- && isset ($ this ->ruleset [$ code ]['properties ' ][$ name ]) === true
989+ && isset ($ this ->ruleset [$ code ]['properties ' ][$ name ][ ' value ' ] ) === true
984990 ) {
985- $ values = $ this ->ruleset [$ code ]['properties ' ][$ name ];
991+ $ values = $ this ->ruleset [$ code ]['properties ' ][$ name ][ ' value ' ] ;
986992 }
987993
988994 if (isset ($ prop ->element ) === true ) {
@@ -1017,7 +1023,10 @@ private function processRule($rule, $newSniffs, $depth=0)
10171023 }
10181024 }//end if
10191025
1020- $ this ->ruleset [$ code ]['properties ' ][$ name ] = $ values ;
1026+ $ this ->ruleset [$ code ]['properties ' ][$ name ] = [
1027+ 'value ' => $ values ,
1028+ 'scope ' => $ propertyScope ,
1029+ ];
10211030 if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
10221031 echo str_repeat ("\t" , $ depth );
10231032 echo "\t\t=> array property \"$ name \" set to \"$ printValue \"" ;
@@ -1028,7 +1037,10 @@ private function processRule($rule, $newSniffs, $depth=0)
10281037 echo PHP_EOL ;
10291038 }
10301039 } else {
1031- $ this ->ruleset [$ code ]['properties ' ][$ name ] = (string ) $ prop ['value ' ];
1040+ $ this ->ruleset [$ code ]['properties ' ][$ name ] = [
1041+ 'value ' => (string ) $ prop ['value ' ],
1042+ 'scope ' => $ propertyScope ,
1043+ ];
10321044 if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
10331045 echo str_repeat ("\t" , $ depth );
10341046 echo "\t\t=> property \"$ name \" set to \"" .(string ) $ prop ['value ' ].'" ' ;
@@ -1218,8 +1230,8 @@ public function populateTokenListeners()
12181230
12191231 // Set custom properties.
12201232 if (isset ($ this ->ruleset [$ sniffCode ]['properties ' ]) === true ) {
1221- foreach ($ this ->ruleset [$ sniffCode ]['properties ' ] as $ name => $ value ) {
1222- $ this ->setSniffProperty ($ sniffClass , $ name , $ value );
1233+ foreach ($ this ->ruleset [$ sniffCode ]['properties ' ] as $ name => $ settings ) {
1234+ $ this ->setSniffProperty ($ sniffClass , $ name , $ settings );
12231235 }
12241236 }
12251237
@@ -1286,18 +1298,76 @@ public function populateTokenListeners()
12861298 *
12871299 * @param string $sniffClass The class name of the sniff.
12881300 * @param string $name The name of the property to change.
1289- * @param string $value The new value of the property.
1301+ * @param array $settings Array with the new value of the property and the scope of the property being set .
12901302 *
12911303 * @return void
1304+ *
1305+ * @throws \PHP_CodeSniffer\Exceptions\RuntimeException When attempting to set a non-existent property on a sniff
1306+ * which doesn't declare the property or explicitly supports
1307+ * dynamic properties.
12921308 */
1293- public function setSniffProperty ($ sniffClass , $ name , $ value )
1309+ public function setSniffProperty ($ sniffClass , $ name , $ settings )
12941310 {
12951311 // Setting a property for a sniff we are not using.
12961312 if (isset ($ this ->sniffs [$ sniffClass ]) === false ) {
12971313 return ;
12981314 }
12991315
1300- $ name = trim ($ name );
1316+ $ name = trim ($ name );
1317+ $ propertyName = $ name ;
1318+ if (substr ($ propertyName , -2 ) === '[] ' ) {
1319+ $ propertyName = substr ($ propertyName , 0 , -2 );
1320+ }
1321+
1322+ /*
1323+ * BC-compatibility layer for $settings using the pre-PHPCS 3.8.0 format.
1324+ *
1325+ * Prior to PHPCS 3.8.0, `$settings` was expected to only contain the new _value_
1326+ * for the property (which could be an array).
1327+ * Since PHPCS 3.8.0, `$settings` is expected to be an array with two keys: 'scope'
1328+ * and 'value', where 'scope' indicates whether the property should be set to the given 'value'
1329+ * for one individual sniff or for all sniffs in a standard.
1330+ *
1331+ * This BC-layer is only for integrations with PHPCS which may call this method directly
1332+ * and will be removed in PHPCS 4.0.0.
1333+ */
1334+
1335+ if (is_array ($ settings ) === false
1336+ || isset ($ settings ['scope ' ], $ settings ['value ' ]) === false
1337+ ) {
1338+ // This will be an "old" format value.
1339+ $ settings = [
1340+ 'value ' => $ settings ,
1341+ 'scope ' => 'standard ' ,
1342+ ];
1343+
1344+ trigger_error (
1345+ __FUNCTION__ .': the format of the $settings parameter has changed from (mixed) $value to array( \'scope \' => \'sniff|standard \', \'value \' => $value). Please update your integration code. See PR #3629 for more information. ' ,
1346+ E_USER_DEPRECATED
1347+ );
1348+ }
1349+
1350+ $ isSettable = false ;
1351+ $ sniffObject = $ this ->sniffs [$ sniffClass ];
1352+ if (property_exists ($ sniffObject , $ propertyName ) === true
1353+ || ($ sniffObject instanceof stdClass) === true
1354+ || method_exists ($ sniffObject , '__set ' ) === true
1355+ ) {
1356+ $ isSettable = true ;
1357+ }
1358+
1359+ if ($ isSettable === false ) {
1360+ if ($ settings ['scope ' ] === 'sniff ' ) {
1361+ $ notice = "Ruleset invalid. Property \"$ propertyName \" does not exist on sniff " ;
1362+ $ notice .= array_search ($ sniffClass , $ this ->sniffCodes , true );
1363+ throw new RuntimeException ($ notice );
1364+ }
1365+
1366+ return ;
1367+ }
1368+
1369+ $ value = $ settings ['value ' ];
1370+
13011371 if (is_string ($ value ) === true ) {
13021372 $ value = trim ($ value );
13031373 }
@@ -1312,7 +1382,7 @@ public function setSniffProperty($sniffClass, $name, $value)
13121382 } else if ($ value === 'false ' ) {
13131383 $ value = false ;
13141384 } else if (substr ($ name , -2 ) === '[] ' ) {
1315- $ name = substr ( $ name , 0 , - 2 ) ;
1385+ $ name = $ propertyName ;
13161386 $ values = [];
13171387 if ($ value !== null ) {
13181388 foreach (explode (', ' , $ value ) as $ val ) {
@@ -1328,7 +1398,7 @@ public function setSniffProperty($sniffClass, $name, $value)
13281398 $ value = $ values ;
13291399 }
13301400
1331- $ this -> sniffs [ $ sniffClass ] ->$ name = $ value ;
1401+ $ sniffObject ->$ name = $ value ;
13321402
13331403 }//end setSniffProperty()
13341404
0 commit comments