!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.3.27 

uname -a: Linux pdx1-shared-a4-04 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64 

uid=6659440(dh_z2jmpm) gid=2086089(pg10499364) groups=2086089(pg10499364)  

Safe-mode: OFF (not secure)

/usr/local/wp/vendor/wp-coding-standards/wpcs/WordPress/Sniffs/Arrays/   drwxr-xr-x
Free 711.97 GB of 879.6 GB (80.94%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     MultipleStatementAlignmentSniff.php (19.42 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/**
 * WordPress Coding Standard.
 *
 * @package WPCS\WordPressCodingStandards
 * @link    https://github.com/WordPress/WordPress-Coding-Standards
 * @license https://opensource.org/licenses/MIT MIT
 */

namespace WordPressCS\WordPress\Sniffs\Arrays;

use PHPCSUtils\Tokens\Collections;
use PHPCSUtils\Utils\Arrays;
use PHPCSUtils\Utils\PassedParameters;
use WordPressCS\WordPress\Sniff;

/**
 * Enforces alignment of the double arrow assignment operator for multi-item, multi-line arrays.
 *
 * - Align the double arrow operator to the same column for each item in a multi-item array.
 * - Allows for setting a maxColumn property to aid in managing line-length.
 * - Allows for new line(s) before a double arrow (configurable).
 * - Allows for handling multi-line array items differently if so desired (configurable).
 *
 * @link https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/#indentation
 *
 * @since 0.14.0
 *
 * {@internal This sniff should eventually be pulled upstream as part of a solution
 * for https://github.com/squizlabs/PHP_CodeSniffer/issues/582 }}
 */
final class MultipleStatementAlignmentSniff extends Sniff {

    /**
     * Whether or not to ignore an array item for the purpose of alignment
     * when a new line is found between the array key and the double arrow.
     *
     * @since 0.14.0
     *
     * @var bool
     */
    public $ignoreNewlines = true;

    /**
     * Whether the alignment should be exact.
     *
     * Exact in this context means "largest index key + 1 space".
     * When `false`, that is seen as the minimum alignment.
     *
     * @since 0.14.0
     *
     * @var bool
     */
    public $exact = true;

    /**
     * The maximum column on which the double arrow alignment should be set.
     *
     * This property allows for limiting the whitespace padding to prevent
     * overly long lines.
     *
     * If this value is set to, for instance, 60, it will:
     * - if the expected column < 60, align at the expected column.
     * - if the expected column >= 60, align at column 60.
     *   - for the outliers, i.e. the array indexes where the end position
     *     goes past column 60, it will not align the arrow, the sniff will
     *     just make sure there is only one space between the end of the
     *     array index and the double arrow.
     *
     * The column value is regarded as a hard value, i.e. includes indentation,
     * so setting it very low is not a good idea.
     *
     * @since 0.14.0
     *
     * @var int
     */
    public $maxColumn = 1000;

    /**
     * Whether or not to align the arrow operator for multi-line array items.
     *
     * Whether or not an item is regarded as multi-line is based on the **value**
     * of the item, not the key.
     *
     * Valid values are:
     * - 'always':   Default. Align all arrays items regardless of single/multi-line.
     * - 'never':    Never align array items which span multiple lines.
     *               This will enforce one space between the array index and the
     *               double arrow operator for multi-line array items, independently
     *               of the alignment of the rest of the array items.
     *               Multi-line items where the arrow is already aligned with the
     *               "expected" alignment, however, will be left alone.
     * - operator :  Only align the operator for multi-line arrays items if the
     *   + number    percentage of multi-line items passes the comparison.
     *               - As it is a percentage, the number has to be between 0 and 100.
     *               - Supported operators: <, <=, >, >=, ==, =, !=, <>
     *               - The percentage is calculated against all array items
     *                 (with and without assignment operator).
     *               - The (new) expected alignment will be calculated based only
     *                 on the items being aligned.
     *               - Multi-line items where the arrow is already aligned with the
     *                 (new) "expected" alignment, however, will be left alone.
     *               Examples:
     *               * Setting this to `!=100` or `<100` means that alignment will
     *                 be enforced, unless *all* array items are multi-line.
     *                 This is probably the most commonly desired situation.
     *               * Setting this to `=100` means that alignment will only
     *                 be enforced, if *all* array items are multi-line.
     *               * Setting this to `<50` means that the majority of array items
     *                 need to be single line before alignment is enforced for
     *                 multi-line items in the array.
     *               * Setting this to `=0` is useless as in that case there are
     *                 no multi-line items in the array anyway.
     *
     * This setting will respect the `ignoreNewlines` and `maxColumn` settings.
     *
     * @since 0.14.0
     *
     * @var string|int
     */
    public $alignMultilineItems = 'always';

    /**
     * Storage for parsed $alignMultilineItems operator part.
     *
     * @since 0.14.0
     *
     * @var string
     */
    private $operator;

    /**
     * Storage for parsed $alignMultilineItems numeric part.
     *
     * Stored as a string as the comparison will be done string based.
     *
     * @since 0.14.0
     *
     * @var string
     */
    private $number;

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @since 0.14.0
     *
     * @return array
     */
    public function register() {
        return Collections::arrayOpenTokensBC();
    }

    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @since 0.14.0
     *
     * @param int $stackPtr The position of the current token in the stack.
     *
     * @return int|void Integer stack pointer to skip forward or void to continue
     *                  normal file processing.
     */
    public function process_token( $stackPtr ) {

        if ( isset( Collections::shortArrayListOpenTokensBC()[ $this->tokens[ $stackPtr ]['code'] ] )
            && Arrays::isShortArray( $this->phpcsFile, $stackPtr ) === false
        ) {
            // Short list, not short array.
            return;
        }

        /*
         * Determine the array opener & closer.
         */
        $array_open_close = Arrays::getOpenClose( $this->phpcsFile, $stackPtr );
        if ( false === $array_open_close ) {
            // Array open/close could not be determined.
            return;
        }

        $opener = $array_open_close['opener'];
        $closer = $array_open_close['closer'];

        $array_items = PassedParameters::getParameters( $this->phpcsFile, $stackPtr );
        if ( empty( $array_items ) ) {
            return;
        }

        // Pass off to either the single line or multi-line array analysis.
        if ( $this->tokens[ $opener ]['line'] === $this->tokens[ $closer ]['line'] ) {
            return $this->process_single_line_array( $stackPtr, $array_items, $opener, $closer );
        } else {
            return $this->process_multi_line_array( $stackPtr, $array_items, $opener, $closer );
        }
    }

    /**
     * Process a single-line array.
     *
     * While the WP standard does not allow single line multi-item associative arrays,
     * this sniff should function independently of that.
     *
     * The `WordPress.WhiteSpace.OperatorSpacing` sniff already covers checking that
     * there is a space between the array key and the double arrow, but doesn't
     * enforce it to be exactly one space for single line arrays.
     * That is what this method covers.
     *
     * @since 0.14.0
     *
     * @param int   $stackPtr The position of the current token in the stack.
     * @param array $items    Info array containing information on each array item.
     * @param int   $opener   The position of the array opener.
     * @param int   $closer   The position of the array closer.
     *
     * @return int|void Integer stack pointer to skip forward or void to continue
     *                  normal file processing.
     */
    protected function process_single_line_array( $stackPtr, $items, $opener, $closer ) {
        /*
         * For single line arrays, we don't care about what level the arrow is from.
         * Just find and fix them all.
         */
        $next_arrow = $this->phpcsFile->findNext(
            \T_DOUBLE_ARROW,
            ( $opener + 1 ),
            $closer
        );

        while ( false !== $next_arrow ) {
            if ( \T_WHITESPACE === $this->tokens[ ( $next_arrow - 1 ) ]['code'] ) {
                $space_length = $this->tokens[ ( $next_arrow - 1 ) ]['length'];
                if ( 1 !== $space_length ) {
                    $error = 'Expected 1 space between "%s" and double arrow; %s found';
                    $data  = array(
                        $this->tokens[ ( $next_arrow - 2 ) ]['content'],
                        $space_length,
                    );

                    $fix = $this->phpcsFile->addFixableWarning( $error, $next_arrow, 'SpaceBeforeDoubleArrow', $data );
                    if ( true === $fix ) {
                        $this->phpcsFile->fixer->replaceToken( ( $next_arrow - 1 ), ' ' );
                    }
                }
            }

            // Find the position of the next double arrow.
            $next_arrow = $this->phpcsFile->findNext(
                \T_DOUBLE_ARROW,
                ( $next_arrow + 1 ),
                $closer
            );
        }

        // Ignore any child-arrays as the double arrows in these will already have been handled.
        return ( $closer + 1 );
    }

    /**
     * Process a multi-line array.
     *
     * @since 0.14.0
     *
     * @param int   $stackPtr The position of the current token in the stack.
     * @param array $items    Info array containing information on each array item.
     * @param int   $opener   The position of the array opener.
     * @param int   $closer   The position of the array closer.
     *
     * @return void
     */
    protected function process_multi_line_array( $stackPtr, $items, $opener, $closer ) {

        $this->maxColumn = (int) $this->maxColumn;
        $this->validate_align_multiline_items();

        /*
         * Determine what the spacing before the arrow should be.
         *
         * Will unset any array items without double arrow and with new line whitespace
         * if newlines are to be ignored, so the second foreach loop only has to deal
         * with items which need attention.
         *
         * This sniff does not take incorrect indentation of array keys into account.
         * That's for the `WordPress.Arrays.ArrayIndentation` sniff to fix.
         * If that would affect the alignment, a second (or third) loop of the fixer
         * will correct it (again) after the indentation has been fixed.
         */
        $index_end_cols    = array(); // Keep track of the end column position of index keys.
        $double_arrow_cols = array(); // Keep track of arrow column position and count.
        $multi_line_count  = 0;
        $total_items       = \count( $items );

        foreach ( $items as $key => $item ) {
            // Find the double arrow if there is one.
            $double_arrow = Arrays::getDoubleArrowPtr( $this->phpcsFile, $item['start'], $item['end'] );
            if ( false === $double_arrow ) {
                unset( $items[ $key ] );
                continue;
            }

            // Find the end of the array key.
            $last_index_token = $this->phpcsFile->findPrevious(
                \T_WHITESPACE,
                ( $double_arrow - 1 ),
                $item['start'],
                true
            );

            if ( true === $this->ignoreNewlines
                && $this->tokens[ $last_index_token ]['line'] !== $this->tokens[ $double_arrow ]['line']
            ) {
                // Ignore this item as it has a new line between the item key and the double arrow.
                unset( $items[ $key ] );
                continue;
            }

            $index_end_position                = ( $this->tokens[ $last_index_token ]['column'] + ( $this->tokens[ $last_index_token ]['length'] - 1 ) );
            $items[ $key ]['operatorPtr']      = $double_arrow;
            $items[ $key ]['last_index_token'] = $last_index_token;
            $items[ $key ]['last_index_col']   = $index_end_position;

            if ( $this->tokens[ $last_index_token ]['line'] === $this->tokens[ $item['end'] ]['line'] ) {
                $items[ $key ]['single_line'] = true;
            } else {
                $items[ $key ]['single_line'] = false;
                ++$multi_line_count;
            }

            if ( ( $index_end_position + 2 ) <= $this->maxColumn ) {
                $index_end_cols[] = $index_end_position;
            }

            if ( ! isset( $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ] ) ) {
                $double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ] = 1;
            } else {
                ++$double_arrow_cols[ $this->tokens[ $double_arrow ]['column'] ];
            }
        }
        unset( $key, $item, $double_arrow, $last_index_token );

        if ( empty( $items ) || empty( $index_end_cols ) ) {
            // No actionable array items found.
            return;
        }

        /*
         * Determine whether the operators for multi-line items should be aligned.
         */
        if ( 'always' === $this->alignMultilineItems ) {
            $alignMultilineItems = true;
        } elseif ( 'never' === $this->alignMultilineItems ) {
            $alignMultilineItems = false;
        } else {
            $percentage = (string) round( ( $multi_line_count / $total_items ) * 100, 0 );

            // Bit hacky, but this is the only comparison function in PHP which allows to
            // pass the comparison operator. And hey, it works ;-).
            $alignMultilineItems = version_compare( $percentage, $this->number, $this->operator );
        }

        /*
         * If necessary, rebuild the $index_end_cols and $double_arrow_cols arrays
         * excluding multi-line items.
         */
        if ( false === $alignMultilineItems ) {
            $select_index_end_cols = array();
            $double_arrow_cols     = array();

            foreach ( $items as $item ) {
                if ( false === $item['single_line'] ) {
                    continue;
                }

                if ( ( $item['last_index_col'] + 2 ) <= $this->maxColumn ) {
                    $select_index_end_cols[] = $item['last_index_col'];
                }

                if ( ! isset( $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ] ) ) {
                    $double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ] = 1;
                } else {
                    ++$double_arrow_cols[ $this->tokens[ $item['operatorPtr'] ]['column'] ];
                }
            }
        }

        /*
         * Determine the expected position of the double arrows.
         */
        if ( ! empty( $select_index_end_cols ) ) {
            $max_index_width = max( $select_index_end_cols );
        } else {
            $max_index_width = max( $index_end_cols );
        }

        $expected_col = ( $max_index_width + 2 );

        if ( false === $this->exact && ! empty( $double_arrow_cols ) ) {
            /*
             * If the alignment does not have to be exact, see if a majority
             * group of the arrows is already at an acceptable position.
             */
            arsort( $double_arrow_cols, \SORT_NUMERIC );
            reset( $double_arrow_cols );
            $count = current( $double_arrow_cols );

            if ( $count > 1 || ( 1 === $count && \count( $items ) === 1 ) ) {
                // Allow for several groups of arrows having the same $count.
                $filtered_double_arrow_cols = array_keys( $double_arrow_cols, $count, true );

                foreach ( $filtered_double_arrow_cols as $col ) {
                    if ( $col > $expected_col && $col <= $this->maxColumn ) {
                        $expected_col = $col;
                        break;
                    }
                }
            }
        }
        unset( $max_index_width, $count, $filtered_double_arrow_cols, $col );

        /*
         * Verify and correct the spacing around the double arrows.
         */
        foreach ( $items as $item ) {
            if ( $this->tokens[ $item['operatorPtr'] ]['column'] === $expected_col
                && $this->tokens[ $item['operatorPtr'] ]['line'] === $this->tokens[ $item['last_index_token'] ]['line']
            ) {
                // Already correctly aligned.
                continue;
            }

            if ( \T_WHITESPACE !== $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['code'] ) {
                $before = 0;
            } elseif ( $this->tokens[ $item['last_index_token'] ]['line'] !== $this->tokens[ $item['operatorPtr'] ]['line'] ) {
                $before = 'newline';
            } else {
                $before = $this->tokens[ ( $item['operatorPtr'] - 1 ) ]['length'];
            }

            /*
             * Deal with index sizes larger than maxColumn and with multi-line
             * array items which should not be aligned.
             */
            if ( ( $item['last_index_col'] + 2 ) > $this->maxColumn
                || ( false === $alignMultilineItems && false === $item['single_line'] )
            ) {

                if ( ( $item['last_index_col'] + 2 ) === $this->tokens[ $item['operatorPtr'] ]['column']
                    && $this->tokens[ $item['operatorPtr'] ]['line'] === $this->tokens[ $item['last_index_token'] ]['line']
                ) {
                    // MaxColumn/Multi-line item exception, already correctly aligned.
                    continue;
                }

                $prefix = 'LongIndex';
                if ( false === $alignMultilineItems && false === $item['single_line'] ) {
                    $prefix = 'MultilineItem';
                }

                $error_code = $prefix . 'SpaceBeforeDoubleArrow';
                if ( 0 === $before ) {
                    $error_code = $prefix . 'NoSpaceBeforeDoubleArrow';
                }

                $fix = $this->phpcsFile->addFixableWarning(
                    'Expected 1 space between "%s" and double arrow; %s found.',
                    $item['operatorPtr'],
                    $error_code,
                    array(
                        $this->tokens[ $item['last_index_token'] ]['content'],
                        $before,
                    )
                );

                if ( true === $fix ) {
                    $this->phpcsFile->fixer->beginChangeset();

                    // Remove whitespace tokens between the end of the index and the arrow, if any.
                    for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) {
                        $this->phpcsFile->fixer->replaceToken( $i, '' );
                    }

                    // Add the correct whitespace.
                    $this->phpcsFile->fixer->addContent( $item['last_index_token'], ' ' );

                    $this->phpcsFile->fixer->endChangeset();
                }
                continue;
            }

            /*
             * Deal with the space before double arrows in all other cases.
             */
            $expected_whitespace = $expected_col - ( $this->tokens[ $item['last_index_token'] ]['column'] + $this->tokens[ $item['last_index_token'] ]['length'] );

            $fix = $this->phpcsFile->addFixableWarning(
                'Array double arrow not aligned correctly; expected %s space(s) between "%s" and double arrow, but found %s.',
                $item['operatorPtr'],
                'DoubleArrowNotAligned',
                array(
                    $expected_whitespace,
                    $this->tokens[ $item['last_index_token'] ]['content'],
                    $before,
                )
            );

            if ( true === $fix ) {
                if ( 0 === $before || 'newline' === $before ) {
                    $this->phpcsFile->fixer->beginChangeset();

                    // Remove whitespace tokens between the end of the index and the arrow, if any.
                    for ( $i = ( $item['last_index_token'] + 1 ); $i < $item['operatorPtr']; $i++ ) {
                        $this->phpcsFile->fixer->replaceToken( $i, '' );
                    }

                    // Add the correct whitespace.
                    $this->phpcsFile->fixer->addContent(
                        $item['last_index_token'],
                        str_repeat( ' ', $expected_whitespace )
                    );

                    $this->phpcsFile->fixer->endChangeset();
                } elseif ( $expected_whitespace > $before ) {
                    // Add to the existing whitespace to prevent replacing tabs with spaces.
                    // That's the concern of another sniff.
                    $this->phpcsFile->fixer->addContent(
                        ( $item['operatorPtr'] - 1 ),
                        str_repeat( ' ', ( $expected_whitespace - $before ) )
                    );
                } else {
                    // Too much whitespace found.
                    $this->phpcsFile->fixer->replaceToken(
                        ( $item['operatorPtr'] - 1 ),
                        str_repeat( ' ', $expected_whitespace )
                    );
                }
            }
        }
    }

    /**
     * Validate that a valid value has been received for the alignMultilineItems property.
     *
     * This message may be thrown more than once if the property is being changed inline in a file.
     *
     * @since 0.14.0
     *
     * @return void
     */
    protected function validate_align_multiline_items() {
        $alignMultilineItems = $this->alignMultilineItems;

        if ( 'always' === $alignMultilineItems || 'never' === $alignMultilineItems ) {
            return;
        } else {
            // Correct for a potentially added % sign.
            $alignMultilineItems = rtrim( $alignMultilineItems, '%' );

            if ( preg_match( '`^([=<>!]{1,2})(100|[0-9]{1,2})$`', $alignMultilineItems, $matches ) > 0 ) {
                $operator = $matches[1];
                $number   = (int) $matches[2];

                if ( \in_array( $operator, array( '<', '<=', '>', '>=', '==', '=', '!=', '<>' ), true ) === true
                    && ( $number >= 0 && $number <= 100 )
                ) {
                    $this->alignMultilineItems = $alignMultilineItems;
                    $this->number              = (string) $number;
                    $this->operator            = $operator;
                    return;
                }
            }
        }

        $this->phpcsFile->addError(
            'Invalid property value passed: "%s". The value for the "alignMultilineItems" property for the "WordPress.Arrays.MultipleStatementAlignment" sniff should be either "always", "never" or an comparison operator + a number between 0 and 100.',
            0,
            'InvalidPropertyPassed',
            array( $this->alignMultilineItems )
        );

        // Reset to the default if an invalid value was received.
        $this->alignMultilineItems = 'always';
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0122 ]--