fqcn=$strFullQualifiedClassName; //echo "DwSource :".strlen($clearSource)."\r\n"; $this->clearSource=$clearSource;// Encoding::UTF8FixWin1252Chars($clearSource); //echo "DwSource :".strlen($this->clearSource)."\r\n"; $nameSpace = $this->readNameSpace(); /* if ( is_string( $nameSpace ) ) { //echo "DwSource nameSpace:$nameSpace\r\n"; $this->dwNameSpace = DwNameSpace::getNameSpace( $nameSpace ); //echo "DwSource use:".print_r( $this->readUses(), true )."\r\n"; //echo "DwSource class:".print_r( $this->readClass(), true )."\r\n"; //echo "DwSource function:".print_r( $this->readFunctions(), true )."\r\n"; } //*/ } public function getSource() : string { return $this->clearSource; } private $constList = null; public function getConstants() : ?array { if ( is_null( $this->constList ) ) $this->constList = $this->constParse(); return $this->constList; } // PerPlexity Production : self::tokenGetAll( $this->fqcn ,$this->getSource() ); static function tokenGetAll( string $className ,string $str ) : array { //if ( class_exists( "\ReflectionClass" ) ) // $constants = ( new \ReflectionClass( $className ) )->getConstants(); //else { $matches = array(); // Fallback: regex based constant parsing (less accurate, for emergency only) \preg_match_all('/const\s+([A-Za-z0-9_]+)\s*=\s*([^\;]+)\;/', $str, $matches, \PREG_SET_ORDER); $constants = array(); foreach ($matches as $m) { //echo $m[1].":".$m[2].\PHP_EOL; $constants[$m[1]] = \trim($m[2], "\"' "); } //} return $constants; } static function stdTokenGetAll( string $className ,string $str ) : array { $tokens = \token_get_all( $str ); $const = false; $name = ''; $constants = array(); foreach ( $tokens as $idx => $token ) { if ( \is_array( $token ) ) { if ($token[0] != T_WHITESPACE) { if ($token[0] == T_CONST && $token[1] == 'const') { //echo "const found\r\n"; $const = true; $name = false; } else if ($token[0] == T_STRING && $const) { $const = false; $name = $token[1]; $constants[$name] = null; } else if ( ( $token[0] == T_LNUMBER || $token[0] == T_CONSTANT_ENCAPSED_STRING ) && $name ) { $constants[$name] = $token[1]; $name = false; } } //$tokens[$idx][0]=\token_name( $token[0] ); } else if ($token != '=') { $const = false; $name = ''; } } return $constants; } protected function constParse( ) : ?array { if ( function_exists( "token_get_all" ) ) $constants = self::stdTokenGetAll( $this->fqcn ,$this->getSource() ); else $constants = self::tokenGetAll( $this->fqcn ,$this->getSource() ); return $constants; } private function readNameSpace( ) { $nameSpace = null; $matches = array(); if ( preg_match_all( '/^.*namespace[\s]*(.*);[\s\S]*$/m' ,$this->clearSource ,$matches ,PREG_OFFSET_CAPTURE ) ){ $nameSpace = $matches[1][0][0];} //else echo "no namespace in \r\n".$this->clearSource."\r\n"; return $nameSpace; }//^[\s]*class[\s]*(.*){[\s]*$ private function readUses( ) { $uses = array("\Exception" => "Exception"); $matches = array(); if ( preg_match_all( '/^[\s]*use[\s]*(.*)[\s]as[\s]*(.*);[\s]*$/m' ,$this->clearSource ,$matches ,PREG_OFFSET_CAPTURE ) ) { for ($cpt = 0;$cpt < sizeof($matches[0]);$cpt++) { $uses[$matches[1][$cpt][0]]=$matches[2][$cpt][0]; } } //else echo "no match use in ".$this->clearSource; return $uses; } private function readClass( ) { $className = ""; $matches = array(); if ( preg_match_all( '/^[\s]*class[\s]*(.*){[\s]*$/m' ,$this->clearSource ,$matches ,PREG_OFFSET_CAPTURE ) ) { $className = $matches[1][0][0]; } else { $matches = array(); if ( preg_match_all( '/^[\s]*interface[\s]*(.*){[\s]*$/m' ,$this->clearSource ,$matches ,PREG_OFFSET_CAPTURE ) ) { $className = "(interface)".$matches[1][0][0]; } } return $className; } private function readFunctions( ) { $functions = array(); $matches = array(); if ( preg_match_all( '/^.*[\s]+function[\s]+(.*)[\s]*\({1}.*\){1}[\s]*{+.*$/m' ,$this->clearSource ,$matches ,PREG_OFFSET_CAPTURE ) ) { for ($cptFunction = 0;$cptFunction < sizeof($matches[1]);$cptFunction++) { $functions[]=$matches[1][$cptFunction][0]; } } return $functions; } ///* public function __destruct() { //$this->log->trace( "." ); foreach( $this as $key => $toDestruct ) if ( isset( $this->$key ) ) unset( $this->$key ); //parent::__destruct(); } //*/ public function getClassName( bool $fqcn=null ) : string { return self::getStaticClassName( $fqcn ); } public static function getStaticClassName( bool $fqcn=null ) : string { return /*$fqcn ? parent::getStaticClassName( $fqcn ).self::CLASS_SEPARATOR.__CLASS__ : */__CLASS__; } //\darkphp\source\DwSource::classNameToFileName( $strFullQualifiedClassName ) : string; public static function classNameToFileName( string $strFullQualifiedClassName ) : string { return self::classNameToFolder ( $strFullQualifiedClassName ).".php"; } //\darkphp\source\DwSource::classNameToFolder( $strFullQualifiedClassName ) : string; public static function classNameToFolder( string $strFullQualifiedClassName ) : string { return \str_replace( array( \T_NS_SEPARATOR, '\\' ) ,\DIRECTORY_SEPARATOR ,$strFullQualifiedClassName ); // return \str_replace( \T_NS_SEPARATOR, \DIRECTORY_SEPARATOR, $strFullQualifiedClassName ); } //darkphp\source\DwSource::getLine( $content ,$line ) public static function getLine( string $content, int $line ) : string { $tabLines = \preg_split( "/\r\n|\n|\r/" ,$content ); // $str=""; // $str .= "\t\t\t\t code [".( $line - 1 )."]".$tabLines[ $line - 1 ]."\r\n"; // $str .= "\t\t\t\t code [!".( $line )."]".$tabLines[ $line ]."\r\n"; // $str .= "\t\t\t\t code [".( $line + 1 )."]".$tabLines[ $line + 1 ]; return "(".( $line ).")".(isset( $tabLines[ $line ] ) ? $tabLines[ $line ] : $content ); } /** * Attempts to shorten the given class name to the desired length. * * This is done by separating the class name into fragments (delimited * by \ or .) and trimming individual fragments, starting with the left, * until desired length has been reached. * * The final fragment (i.e. class name) will never be shortened so the * result may still be longer than given length. * * @param string $name The (qualified) class name. * @param integer $length The length to shorten to. If null or 0 is given, * the name will be returned without shortening. */ //darkphp\source\DwSource::shortenClassName public static function shortenClassName($name, $length) { if ($length === null || $length < 0) { return $name; } $name = str_replace('.', '\\', $name); $name = trim($name, ' \\'); // Check if any shortening is required $currentLength = strlen($name); if ($currentLength <= $length) { return $name; } // Split name into fragments $fragments = explode('\\', $name); // If zero length is specified, return only last fragment if ($length == 0) { return array_pop($fragments); } // If the name splits to only one fragment, then it cannot be shortened $count = count($fragments); if ($count == 1) { return $name; } foreach($fragments as $key => &$fragment) { // Never shorten last fragment if ($key == $count - 1) { break; } // Check for empty fragments (shouldn't happen but it's possible) $fragLen = strlen($fragment); if ($fragLen <= 1) { continue; } // Shorten fragment to one character and check if total length satisfactory $fragment = substr($fragment, 0, 1); $currentLength = $currentLength - $fragLen + 1; if ($currentLength <= $length) { break; } } unset($fragment); return implode('\\', $fragments); } /** * Splits a fully qualified class name into fragments delimited by the * namespace separator (\). * * For backward compatibility, a dot (.) can be used as a delimiter as * well. * * @param string $name * * @return array Class name split into fragments. */ //darkphp\source\DwSource::tokenizeClassName public static function tokenizeClassName($name) { $name = str_replace('.', '\\', $name); $name = trim($name, ' \\'); $fragments = explode('\\', $name); foreach($fragments as $key => $fragment) { if (trim($fragment) === '') { unset($fragments[$key]); } } return $fragments; } //darkphp\source\DwSource::codeToNs( $content ) public static function codeToNs( string $content ) { //\preg_match( '/.*namespace (.*\w+);?/' ,$content ,$matches ); \preg_match( '/namespace\s+([^\s;]+)\s*;/' ,$content ,$matches );// correction <= Preplexity Production //\preg_match('/namespace\s+([a-zA-Z0-9_\\\\]+)\s*;/', $content, $matches); // robuste correction <= Preplexity Production return isset( $matches[1] ) ? $matches[1] : "echec codeToNs :".$content;//self::getLine( $content ,2 ); } //darkphp\source\DwSource::codeToClass( $content ) public static function codeToClass( string $content ) { //\preg_match( '/.*class (\w+)( extends .*)?( implements .*)?\s*{/' ,$content ,$matches ); //\preg_match( '/\s*(final\s*)?(abstract\s*)?class\s*(\S*)\s*(extends\s*\S*)?\s*(implements\s*\S*)?\s*{+/' ,$content ,$matches ); //\preg_match('/\s*(final\s*)?(abstract\s*)?class\s+([a-zA-Z0-9_]+)\s*/', $content, $matches);// correction <= Preplexity Production \preg_match('/\s*(final\s*)?(abstract\s*)?class\s+([a-zA-Z0-9_]+)\s*(?:extends\s+[a-zA-Z0-9_\\\\]+)?\s*(?:implements\s+[a-zA-Z0-9_,\s\\\\]+)?\s*{/', $content, $matches);// correction with extends/implements <= Preplexity Production return isset( $matches[3] ) ? $matches[3] : "echec codeToClass :".self::getLine( $content ,2 ); } //darkphp\source\DwSource::classNameToTopName( $this->getClassName() ) public static function classNameToTopName( string $fqcn ) : string { return \substr( $fqcn, \strrpos( $fqcn ,"\\" ) + 1 ); //return \substr( $fqcn, \strrpos( $fqcn ,\T_NS_SEPARATOR ) + 1 ); //return \strrev( \strtok( \strrev( $this->getClassName() ), "\\") ) } //darkphp\source\DwSource::classNameToSectionName( $this->getClassName() ) public static function classNameToSectionName( string $fqcn ) : string { $topName = self::classNameToTopName( $fqcn ); return \substr( $fqcn ,0 ,\strlen( $fqcn ) - ( \strlen( $topName ) + 1 ) ); } //darkphp\source\DwSource::classNameToFirstSectionName( $this->getClassName() ) public static function classNameToFirstSectionName( string $fqcn ) : string { $sectionsName = self::classNameToSectionName( $fqcn ); return \substr( $sectionsName, \strrpos( $sectionsName ,"\\" ) + 1 ); } public static function classNameToLastSectionName( string $fqcn ) : string { $sectionsName = self::classNameToSectionName( $fqcn ); return \substr( $sectionsName, 0 ,\strpos( $sectionsName ,"\\" ,1 ) ); } //darkphp\source\DwSource::formatFileLine( $file ,$line ); public static function formatFileLine( string $file ,int $line ,string $separate = "\r\n\t\t\t " ) : string { $toString=""; if ( \is_file( $file ) ) $toString .=" file '".( $file )."'".$separate; else { if ( $line <= 0 ) $toString .= " unknow '". \substr( \urldecode( $file ) ,10 ) ."'".$separate; } //else if ( class_exists( "\\darkphp\\autoLoad\\DwAutoLoad", false ) ) { if ( \darkphp\autoload\DwAutoLoad::isFile( $file ) ) $fileContent = \darkphp\autoload\DwAutoLoad::getFile( $file ); else $fileContent = \darkphp\autoload\DwAutoLoad::decodeFile( $file ); } else $fileContent = "file $file not decoded, no autoload class exist!"; if ( isset( $fileContent ) && \is_string( $fileContent ) ) { //$toString .=" object '".( DwSource::codeToNs( $fileContent ). "\\" . DwSource::codeToClass( $fileContent ) )."'".$separate; $toString .= DwSource::getLine( $fileContent ,$line - 1 ); } else $toString .=" echec get content! file:'".\substr( $file ,10 )."'"; return $toString; } public static function formatContentLine( string $content ,int $line ,string $separate = "\r\n\t\t\t " ) : string { $toString=""; if ( \is_string( $content ) ) { $toString .=" object '".( DwSource::codeToNs( $content ). "\\" . DwSource::codeToClass( $content ) )."'".$separate; $toString .= DwSource::getLine( $content ,$line - 1 ); } else $toString .=" echec get content! file:'".\substr( $file ,10 )."'"; return $toString; } } ?>