<?xml version="1.0"?>
<ruleset>
    <arg name="basepath" value="." />
    <arg name="extensions" value="php" />
    <arg name="parallel" value="80" />
    <arg name="cache" value=".phpcs-cache" />
    <arg name="colors" />

    <!-- Ignore warnings (n), show progress of the run (p), and show sniff names (s) -->
    <arg value="nps"/>

    <file>src</file>
    <file>examples</file>
    <file>tests</file>
    <file>tools</file>

    <!-- ****************************************** -->
    <!-- Import rules from doctrine/coding-standard -->
    <!-- ****************************************** -->
    <rule ref="Doctrine">
        <!-- ********************************************** -->
        <!-- Exclude sniffs that require newer PHP versions -->
        <!-- ********************************************** -->

        <!-- Requires PHP 7.4 -->
        <exclude name="SlevomatCodingStandard.ControlStructures.RequireNullCoalesceEqualOperator" />

        <!-- Requires PHP 8.0 -->
        <exclude name="SlevomatCodingStandard.Classes.ModernClassNameReference.ClassNameReferencedViaFunctionCall" />


        <!-- *********************************** -->
        <!-- Exclude sniffs that cause BC breaks -->
        <!-- *********************************** -->
        <exclude name="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming" />
        <exclude name="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming" />
        <exclude name="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming" />
        <exclude name="SlevomatCodingStandard.Classes.SuperfluousTraitNaming" />

        <!-- Can cause subtle BC breaks -->
        <exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes" />


        <!-- **************************************** -->
        <!-- Exclude sniffs that force unwanted style -->
        <!-- **************************************** -->
        <exclude name="Generic.Formatting.MultipleStatementAlignment" />
        <exclude name="Squiz.Commenting.FunctionComment.ThrowsNoFullStop" />

        <!-- Keep long typehints (for now) -->
        <exclude name="PSR12.Keywords.ShortFormTypeKeywords" />
        <exclude name="SlevomatCodingStandard.PHP.TypeCast.InvalidCastUsed" />
        <exclude name="SlevomatCodingStandard.TypeHints.LongTypeHints" />


        <!-- ************************************************ -->
        <!-- Exclude sniffs that may cause functional changes -->
        <!-- ************************************************ -->
        <exclude name="Generic.PHP.ForbiddenFunctions.FoundWithAlternative" />
        <exclude name="SlevomatCodingStandard.ControlStructures.DisallowYodaComparison" />
        <exclude name="SlevomatCodingStandard.ControlStructures.EarlyExit" />
        <exclude name="SlevomatCodingStandard.ControlStructures.UselessIfConditionWithReturn" />
        <exclude name="SlevomatCodingStandard.Functions.StaticClosure" />
        <exclude name="SlevomatCodingStandard.Functions.UnusedInheritedVariablePassedToClosure" />
        <exclude name="SlevomatCodingStandard.Operators.DisallowEqualOperators" />


        <!-- ********************************************************* -->
        <!-- Exclude sniffs that cause a huge diff - enable separately -->
        <!-- ********************************************************* -->
        <exclude name="SlevomatCodingStandard.Commenting.DocCommentSpacing.IncorrectAnnotationsGroup" />
        <exclude name="Squiz.Strings.DoubleQuoteUsage" />


        <!-- ********************* -->
        <!-- Exclude broken sniffs -->
        <!-- ********************* -->

        <!-- Sniff currently broken when casting arrays, see https://github.com/squizlabs/PHP_CodeSniffer/issues/2937#issuecomment-615498860 -->
        <exclude name="Squiz.Arrays.ArrayDeclaration.ValueNoNewline" />

        <!-- Disable forbidden annotation sniff as excluding @api from the list doesn't work -->
        <exclude name="SlevomatCodingStandard.Commenting.ForbiddenAnnotations.AnnotationForbidden" />
    </rule>


    <!-- ***************************************************** -->
    <!-- Forbid fully qualified names even for colliding names -->
    <!-- ***************************************************** -->
    <rule ref="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly">
        <properties>
            <property name="allowFallbackGlobalConstants" value="false"/>
            <property name="allowFallbackGlobalFunctions" value="false"/>
            <property name="allowFullyQualifiedGlobalClasses" value="false"/>
            <property name="allowFullyQualifiedGlobalConstants" value="false"/>
            <property name="allowFullyQualifiedGlobalFunctions" value="false"/>
            <property phpcs-only="true" name="allowFullyQualifiedNameForCollidingClasses" value="false"/>
            <property phpcs-only="true" name="allowFullyQualifiedNameForCollidingConstants" value="false"/>
            <property phpcs-only="true" name="allowFullyQualifiedNameForCollidingFunctions" value="false"/>
            <property name="searchAnnotations" value="true"/>
        </properties>
    </rule>


    <!-- **************************************************************************** -->
    <!-- Exclude BC breaking type hints for parameters, properties, and return values -->
    <!-- **************************************************************************** -->
    <rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint">
        <properties>
            <!-- Requires PHP 8.0 -->
            <property name="enableMixedTypeHint" value="false" />
            <!-- Requires PHP 8.0 -->
            <property name="enableUnionTypeHint" value="false" />
        </properties>

        <exclude name="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification" />
    </rule>

    <rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
        <properties>
            <!-- Requires PHP 7.4 -->
            <property name="enableNativeTypeHint" value="false" />
            <!-- Requires PHP 8.0 -->
            <property name="enableMixedTypeHint" value="false" />
            <!-- Requires PHP 8.0 -->
            <property name="enableUnionTypeHint" value="false" />
        </properties>

        <exclude name="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification" />
    </rule>

    <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint">
        <properties>
            <!-- Requires PHP 8.0 -->
            <property name="enableStaticTypeHint" value="false" />
            <!-- Requires PHP 8.0 -->
            <property name="enableMixedTypeHint" value="false" />
            <!-- Requires PHP 8.0 -->
            <property name="enableUnionTypeHint" value="false" />
        </properties>

        <exclude name="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification" />
    </rule>


    <!-- ************************************************************************** -->
    <!-- Require type hints for all parameters, properties, and return types in src -->
    <!-- ************************************************************************** -->
    <rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingAnyTypeHint">
        <exclude-pattern>tests</exclude-pattern>
    </rule>
    <rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingAnyTypeHint">
        <exclude-pattern>tests</exclude-pattern>
    </rule>
    <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingAnyTypeHint">
        <exclude-pattern>tests</exclude-pattern>
    </rule>


    <!-- *********************************************************** -->
    <!-- Require native type hints for all code without a BC promise -->
    <!-- *********************************************************** -->
    <rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingNativeTypeHint">
        <exclude-pattern>src</exclude-pattern>
    </rule>
    <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
        <exclude-pattern>src</exclude-pattern>
    </rule>


    <!-- ************************************************************* -->
    <!-- Ignore errors for certain files where this is part of the API -->
    <!-- ************************************************************* -->
    <rule ref="PSR1.Methods.CamelCapsMethodName.NotCamelCaps">
        <exclude-pattern>/src/GridFS/StreamWrapper</exclude-pattern>
        <exclude-pattern>/tests/DocumentationExamplesTest.php</exclude-pattern>
        <exclude-pattern>/tests/GridFS/UnusableStream.php</exclude-pattern>
    </rule>
    <rule ref="PSR1.Classes.ClassDeclaration.MultipleClasses">
        <exclude-pattern>/examples</exclude-pattern>
        <exclude-pattern>/tests/PHPUnit/ConstraintTrait.php</exclude-pattern>
    </rule>
    <rule ref="Squiz.Classes.ClassFileName.NoMatch">
        <exclude-pattern>/examples</exclude-pattern>
    </rule>
</ruleset>
