<?xml version="1.0"?>
<!--
	See:
	- https://www.mediawiki.org/wiki/Manual:Coding_conventions
	- https://pear.php.net/manual/en/package.php.php-codesniffer.annotated-ruleset.php
	- https://github.com/squizlabs/PHP_CodeSniffer/tree/master/CodeSniffer/Standards
-->
<ruleset name="MediaWiki">

	<description>A coding standard for MediaWiki.</description>

	<arg name="tab-width" value="4" />

	<rule ref="Generic.Arrays.DisallowLongArraySyntax" />

	<rule ref="Generic.Classes.DuplicateClassName" />
	<rule ref="Generic.CodeAnalysis.EmptyPHPStatement" />
	<!-- Some people like else { /** comment */ }
	<rule ref="Generic.CodeAnalysis.EmptyStatement" />
	-->
	<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop" />
	<rule ref="Generic.CodeAnalysis.JumbledIncrementer" />
	<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement" />
	<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier" />
	<!--
		https://pear.php.net/bugs/bug.php?id=19950
		<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter" />
	-->
	<!--
		Useless rule. Test is naïve and flags perfectly legit reasons to override
		<rule ref="Generic.CodeAnalysis.UselessOverridingMethod" />
	-->
	<rule ref="Generic.Files.ByteOrderMark" />
	<rule ref="Generic.Files.LineEndings" />
	<rule ref="Generic.Files.LineLength">
		<properties>
			<!-- More than 120 will throw a warning ... -->
			<property name="lineLimit" value="120" />
			<!-- ... but we will most probably never throw an error -->
			<property name="absoluteLineLimit" value="9999" />
		</properties>
	</rule>
	<rule ref="Generic.Files.OneObjectStructurePerFile" />
	<rule ref="Generic.Formatting.DisallowMultipleStatements" />
	<rule ref="Generic.Formatting.MultipleStatementAlignment" />
	<rule ref="Generic.Formatting.MultipleStatementAlignment.NotSameWarning">
		<severity>0</severity>
	</rule>

	<!-- When type casting, do not use a space within or after the cast operator parentheses. -->
	<rule ref="Squiz.WhiteSpace.CastSpacing" />
	<rule ref="Generic.Formatting.SpaceAfterCast">
		<properties>
			<property name="spacing" value="0" />
		</properties>
	</rule>
	<rule ref="Generic.Formatting.SpaceAfterNot">
		<properties>
			<property name="spacing" value="0" />
		</properties>
	</rule>

	<rule ref="Generic.Functions.CallTimePassByReference" />
	<rule ref="Generic.Functions.FunctionCallArgumentSpacing" />
	<rule ref="Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma">
		<!--
			We align certain function calls like this
			define( 'FOO',          1 );
			define( 'A_BIT_LONGER', 2 );
		-->
		<severity>0</severity>
	</rule>
	<rule ref="Generic.Functions.OpeningFunctionBraceKernighanRitchie" />
	<!-- <rule ref="Generic.NamingConventions.CamelCapsFunctionName" /> -->
	<rule ref="Generic.NamingConventions.ConstructorName" />
	<rule ref="Generic.NamingConventions.UpperCaseConstantName" />
	<rule ref="Generic.PHP.CharacterBeforePHPOpeningTag" />
	<rule ref="Generic.PHP.DisallowShortOpenTag" />
	<rule ref="Generic.PHP.DiscourageGoto" />
	<rule ref="Generic.PHP.ForbiddenFunctions" />
	<rule ref="Generic.PHP.LowerCaseConstant" />
	<rule ref="Generic.PHP.LowerCaseKeyword" />
	<rule ref="Generic.PHP.LowerCaseType" />
	<rule ref="Generic.PHP.NoSilencedErrors" />
	<rule ref="Generic.PHP.SAPIUsage" />
	<rule ref="Generic.WhiteSpace.DisallowSpaceIndent" />
	<rule ref="Generic.WhiteSpace.IncrementDecrementSpacing" />
	<rule ref="Generic.WhiteSpace.SpreadOperatorSpacingAfter" />

	<rule ref="PSR2.Classes.ClassDeclaration">
		<exclude name="PSR2.Classes.ClassDeclaration.SpaceBeforeBrace" />
		<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNotAlone" />
		<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceWrongLine" />
		<exclude name="PSR2.Classes.ClassDeclaration.OpenBraceNewLine" />
		<exclude name="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody" />
		<exclude name="PSR2.Classes.ClassDeclaration.ImplementsLine" />
		<exclude name="PSR2.Classes.ClassDeclaration.ExtendsLine" />
	</rule>
	<rule ref="PSR2.Classes.PropertyDeclaration" />
	<rule ref="PSR2.Classes.PropertyDeclaration.Multiple">
		<!-- We tend to declare multiple properties with one statement -->
		<severity>0</severity>
	</rule>
	<rule ref="Generic.ControlStructures.InlineControlStructure" />
	<rule ref="PSR2.Files.EndFileNewline" />
	<rule ref="PSR2.ControlStructures.ElseIfDeclaration" />
	<rule ref="PSR2.Methods.MethodDeclaration" />
	<rule ref="PSR2.Namespaces.NamespaceDeclaration" />
	<rule ref="PSR2.Namespaces.UseDeclaration" />
	<rule ref="PSR2.Methods.FunctionClosingBrace" />

	<rule ref="PSR12.Files.ImportStatement" />
	<rule ref="PSR12.Keywords.ShortFormTypeKeywords" />
	<rule ref="PSR12.Properties.ConstantVisibility" />
	<rule ref="PSR12.Traits.UseDeclaration" />
	<rule ref="PSR12.Traits.UseDeclaration.UseAfterBrace">
		<severity>0</severity>
	</rule>
	<rule ref="PSR12.Traits.UseDeclaration.BlankLineAfterLastUse">
		<severity>0</severity>
	</rule>

	<rule ref="Squiz.CSS.SemicolonSpacing" />
	<rule ref="Squiz.Classes.SelfMemberReference" />
	<rule ref="Squiz.Classes.ValidClassName" />
	<rule ref="Squiz.Functions.FunctionDeclarationArgumentSpacing">
		<properties>
			<property name="equalsSpacing" value="1" />
			<property name="requiredSpacesAfterOpen" value="1" />
			<property name="requiredSpacesBeforeClose" value="1" />
		</properties>
	</rule>
	<rule ref="Squiz.Functions.FunctionDuplicateArgument" />
	<rule ref="Squiz.Operators.ValidLogicalOperators" />
	<rule ref="Squiz.PHP.NonExecutableCode" />
	<rule ref="Squiz.Scope.StaticThisUsage" />
	<rule ref="Squiz.Scope.MemberVarScope" />
	<rule ref="Squiz.Scope.MethodScope" />
	<rule ref="Squiz.Strings.ConcatenationSpacing">
		<properties>
			<property name="spacing" value="1" />
			<property name="ignoreNewlines" value="true" />
		</properties>
	</rule>
	<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing" />
	<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing" />
	<rule ref="Squiz.WhiteSpace.FunctionSpacing">
		<properties>
			<property name="spacing" value="1" />
		</properties>
	</rule>
	<rule ref="Squiz.WhiteSpace.FunctionSpacing.AfterLast">
		<severity>0</severity>
	</rule>
	<rule ref="Squiz.WhiteSpace.FunctionSpacing.BeforeFirst">
		<severity>0</severity>
	</rule>
	<!-- <rule ref="Squiz.WhiteSpace.MemberVarSpacing" /> -->
	<rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing">
		<properties>
			<property name="ignoreNewlines" value="true" />
		</properties>
	</rule>
	<rule ref="Squiz.WhiteSpace.OperatorSpacing">
		<properties>
			<property name="ignoreNewlines" value="true" />
		</properties>
	</rule>
	<rule ref="Squiz.WhiteSpace.ScopeClosingBrace" />
	<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing" />
	<rule ref="Squiz.WhiteSpace.SemicolonSpacing" />
	<rule ref="Squiz.WhiteSpace.SuperfluousWhitespace">
		<!-- Implemented as MediaWiki.WhiteSpace.MultipleEmptyLines -->
		<exclude name="Squiz.WhiteSpace.SuperfluousWhitespace.EmptyLines" />
	</rule>

	<rule ref="Zend.Files.ClosingTag" />
	<rule ref="Generic.PHP.BacktickOperator" />
	<rule ref="Generic.VersionControl.GitMergeConflict" />

	<rule ref="PEAR.Functions.ValidDefaultValue.NotAtEnd" />

	<!-- Exclude common folders from version control or build tools -->
	<exclude-pattern type="relative">^\.git</exclude-pattern>
	<exclude-pattern type="relative">^vendor</exclude-pattern>
	<exclude-pattern type="relative">^node_modules</exclude-pattern>
</ruleset>
