Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/mcoil.corals.io/vendor/kkszymanowski/traitor/src/Handlers/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/mcoil.corals.io/vendor/kkszymanowski/traitor/src/Handlers/AbstractTreeHandler.php
<?php

/*
 * KKSzymanowski/Traitor
 * Add a trait use statement to existing class
 *
 * @package KKSzymanowski/Traitor
 * @author Kuba Szymanowski <[email protected]>
 * @link https://github.com/kkszymanowski/traitor
 * @license MIT
 */

namespace Traitor\Handlers;

use Exception;
use PhpParser\Error;
use PhpParser\Lexer;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Namespace_;
use PhpParser\Node\Stmt\TraitUse;
use PhpParser\Node\Stmt\Use_;

class AbstractTreeHandler implements Handler
{
    /** @var array */
    protected $content;

    /** @var string */
    protected $trait;

    /** @var string */
    protected $traitShortName;

    /** @var string */
    protected $class;

    /** @var string */
    protected $classShortName;

    /** @var array */
    protected $syntaxTree;

    /** @var Namespace_ */
    protected $namespace;

    /** @var array */
    protected $importStatements;

    /** @var array */
    protected $classes;

    /** @var Class_ */
    protected $classAbstractTree;

    /** @var string */
    protected $lineEnding = "\n";

    /**
     * @param  array  $content
     * @param  string  $trait
     * @param  string  $class
     */
    public function __construct($content, $trait, $class)
    {
        $this->content = $content;

        $this->determineLineEnding();

        $this->trait = $trait;
        $traitParts = explode('\\', $trait);
        $this->traitShortName = array_pop($traitParts);

        $this->class = $class;
        $classParts = explode('\\', $class);
        $this->classShortName = array_pop($classParts);
    }

    /**
     * @return $this
     */
    public function handle()
    {
        $this->buildSyntaxTree()
             ->addTraitImport()
             ->buildSyntaxTree()
             ->addTraitUseStatement();

        return $this;
    }

    /**
     * @return string
     */
    public function toString()
    {
        return implode($this->content);
    }

    /**
     * @return array
     */
    public function toArray()
    {
        return $this->content;
    }

    /**
     * @return $this
     *
     * @throws Exception
     */
    protected function buildSyntaxTree()
    {
        $this->parseContent()
             ->retrieveNamespace()
             ->retrieveImports()
             ->retrieveClasses()
             ->findClassDefinition();

        return $this;
    }

    /**
     * @return $this
     */
    protected function addTraitImport()
    {
        if ($this->hasTraitImport()) {
            return $this;
        }

        $lastImport = $this->getLastImport();
        if ($lastImport === false) {
            $lineNumber = $this->classAbstractTree->getLine() - 1;
            $newImport = 'use '.$this->trait.';'.$this->lineEnding;

            array_splice($this->content, $lineNumber, 0, $this->lineEnding);
        } else {
            $lineNumber = $this->getLastImport()->getAttribute('endLine');
            $newImport = 'use '.$this->trait.';'.$this->lineEnding;
        }

        array_splice($this->content, $lineNumber, 0, $newImport);

        return $this;
    }

    /**
     * @return $this
     */
    protected function addTraitUseStatement()
    {
        if ($this->alreadyUsesTrait()) {
            return $this;
        }

        $this->openBracketsIfNecessary();

        $line = $this->getNewTraitUseLine();

        $newTraitUse = static::getIndentation($this->content[$line]).'use '.$this->traitShortName.';'.$this->lineEnding;

        array_splice($this->content, $line, 0, $newTraitUse);

        return $this;
    }

    /**
     * @return $this
     *
     * @throws Exception
     */
    protected function parseContent()
    {
        $flatContent = implode($this->content);

        try {
            $parser = $this->getParser();
            $this->syntaxTree = $parser->parse($flatContent);
        } catch (Error $e) {
            throw new Exception('Error on parsing '.$this->classShortName." class\n".$e->getMessage());
        }

        return $this;
    }

    /**
     * @return $this
     *
     * @throws Exception
     */
    protected function retrieveNamespace()
    {
        $namespaceNode = null;
        foreach ($this->syntaxTree as $item) {
            if ($item instanceof Namespace_) {
                $namespaceNode = $item;
            }
        }

        if (! $namespaceNode) {
//            var_dump($this->syntaxTree);die;
//            throw new Exception("Could not locate namespace definition for class '".$this->classShortName."'");
        }

        $this->namespace = $namespaceNode;

        return $this;
    }

    /**
     * @return $this
     */
    protected function retrieveImports()
    {
        if ($this->namespace === null) {
            $this->importStatements = array_filter($this->syntaxTree, function ($statement) {
                return $statement instanceof Use_;
            });
        } else {
            $this->importStatements = array_filter($this->namespace->stmts, function ($statement) {
                return $statement instanceof Use_;
            });
        }

        return $this;
    }

    /**
     * @return $this
     */
    protected function retrieveClasses()
    {
        if ($this->namespace === null) {
            $this->classes = array_filter($this->syntaxTree, function ($statement) {
                return $statement instanceof Class_;
            });
        } else {
            $this->classes = array_filter($this->namespace->stmts, function ($statement) {
                return $statement instanceof Class_;
            });
        }

        return $this;
    }

    /**
     * @return \PhpParser\Node\Stmt\Use_
     */
    protected function getLastImport()
    {
        return end($this->importStatements);
    }

    /**
     * @return bool
     */
    protected function hasTraitImport()
    {
        foreach ($this->importStatements as $statement) {
            if ($statement->uses[0]->name->toString() == $this->trait) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return bool
     */
    protected function alreadyUsesTrait()
    {
        $traitUses = array_filter($this->classAbstractTree->stmts, function ($statement) {
            return $statement instanceof TraitUse;
        });

        /** @var TraitUse $statement */
        foreach ($traitUses as $statement) {
            foreach ($statement->traits as $traitUse) {
                if ($traitUse->toString() == $this->trait
                    || $traitUse->toString() == $this->traitShortName
                ) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * @return $this
     *
     * @throws Exception
     */
    protected function findClassDefinition()
    {
        foreach ($this->classes as $class) {
            if ($class->name == $this->classShortName) {
                $this->classAbstractTree = $class;

                return $this;
            }
        }

        throw new Exception('Class '.$this->classShortName.' not found');
    }

    /**
     * @return int
     *
     * @throws Exception
     */
    protected function getNewTraitUseLine()
    {
        // If the first statement is a trait use, insert the new trait use before it.
        if (isset($this->classAbstractTree->stmts[0])) {
            $firstStatement = $this->classAbstractTree->stmts[0];

            if ($firstStatement instanceof TraitUse) {
                return $firstStatement->getLine() - 1;
            }
        }

        // If the first statement is not a trait use, insert the new one just after the opening bracket.
        for ($line = $this->classAbstractTree->getLine() - 1; $line < count($this->content); $line++) {
            if (strpos($this->content[$line], '{') !== false) {
                return $line + 1;
            }
        }

        throw new Exception("Opening bracket not found in class [$this->classShortName]");
    }

    protected function openBracketsIfNecessary()
    {
        for ($line = $this->classAbstractTree->getLine() - 1; $line < count($this->content); $line++) {
            $trimmedLine = rtrim($this->content[$line]);

            if (substr($trimmedLine, strlen($trimmedLine) - 2) == '{}') {
                $trimmedLine = rtrim(substr($trimmedLine, 0, strlen($trimmedLine) - 2));
                if (strlen($trimmedLine) == 0) {
                    $this->content[$line] = '{'.$this->lineEnding;
                    array_splice($this->content, $line + 1, 0, '}'.$this->lineEnding);
                } else {
                    $this->content[$line] = $trimmedLine.$this->lineEnding;
                    array_splice($this->content, $line + 1, 0, '{'.$this->lineEnding);
                    array_splice($this->content, $line + 2, 0, '}'.$this->lineEnding);
                }

                $this->buildSyntaxTree();
                break;
            }
        }
    }

    /**
     * Default line ending is set to LF.
     *
     * If there is at least one line in the provided file
     * and it contains CR+LF, change line ending CR+LF.
     *
     * @return $this
     */
    protected function determineLineEnding()
    {
        if (isset($this->content[0]) && strpos($this->content[0], "\r\n") !== false) {
            $this->lineEnding = "\r\n";
        }

        return $this;
    }

    /**
     * @param  $line
     * @return string
     */
    protected static function getIndentation($line)
    {
        preg_match('/^\s*/', $line, $match);

        if (isset($match[0])) {
            $match[0] = trim($match[0], "\n\r");

            if (strlen($match[0]) > 0) {
                return $match[0];
            }
        }

        return str_repeat(' ', 4);
    }

    protected function getParser()
    {
        $refParser = new \ReflectionClass('\PhpParser\Parser');

        if (! $refParser->isInterface()) {
            // If we are running nikic/php-parser 1.*
            return new \PhpParser\Parser(new Lexer());
        } else {
            $parserFactory = new \PhpParser\ParserFactory();

            if (method_exists($parserFactory, 'createForHostVersion')) {
                return $parserFactory->createForHostVersion();
            } elseif (method_exists($parserFactory, 'create')) {
                return $parserFactory->create(\PhpParser\ParserFactory::PREFER_PHP7);
            } else {
                throw new \RuntimeException('Unsupported version of nikic/php-parser');
            }
        }
    }
}

Spamworldpro Mini