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

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-163-generic #173-Ubuntu SMP Tue Oct 14 17:51:00 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/adflow-backend.picotech.app/public_html/vendor/psy/psysh/src/Formatter/   drwxr-xr-x
Free 25.09 GB of 117.98 GB (21.26%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


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

/*
 * This file is part of Psy Shell.
 *
 * (c) 2012-2025 Justin Hileman
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Psy\Formatter;

use 
Psy\Manual\ManualInterface;

/**
 * Formats structured manual data for display at runtime.
 *
 * Takes structured data from the v3 manual format and formats it for display,
 * adapting to terminal width and converting semantic tags to console styles.
 */
class ManualFormatter
{
    
// Maximum width for text wrapping, even on very wide terminals
    
private const MAX_WIDTH 120;

    private 
ManualWrapper $wrapper;
    private 
int $width;
    private ?
ManualInterface $manual;

    
/**
     * @param int                  $width  Terminal width for text wrapping
     * @param ManualInterface|null $manual Optional manual for generating hyperlinks
     */
    
public function __construct(int $width 100, ?ManualInterface $manual null)
    {
        
$this->wrapper = new ManualWrapper();
        
// Cap width at MAX_WIDTH for readability on ultra-wide terminals
        
$this->width \min($widthself::MAX_WIDTH);
        
$this->manual $manual;
    }

    
/**
     * Format structured manual data for display.
     *
     * @param array $data Structured manual data
     */
    
public function format(array $data): string
    
{
        
$output = [];

        
// Format based on type
        
switch ($data['type'] ?? '') {
            case 
'function':
                
$output[] = $this->formatFunction($data);
                break;
            case 
'class':
                
$output[] = $this->formatClass($data);
                break;
            case 
'constant':
                
$output[] = $this->formatConstant($data);
                break;
            default:
                
// Generic fallback
                
if (!empty($data['description'])) {
                    
$output[] = $this->formatDescription($data['description']);
                }
        }

        return 
\implode("\n\n"\array_filter($output))."\n";
    }

    
/**
     * Format a function entry.
     *
     * @param array $data Function data
     */
    
private function formatFunction(array $data): string
    
{
        
$output = [];

        if (!empty(
$data['description'])) {
            
$output[] = $this->formatDescription($data['description']);
        }

        if (!empty(
$data['params'])) {
            
$output[] = $this->formatParameters($data['params']);
        }

        if (!empty(
$data['return'])) {
            
$output[] = $this->formatReturn($data['return']);
        }

        if (!empty(
$data['seeAlso'])) {
            
$output[] = $this->formatSeeAlso($data['seeAlso']);
        }

        return 
\implode("\n\n"\array_filter($output));
    }

    
/**
     * Format a class entry.
     *
     * @param array $data Class data
     */
    
private function formatClass(array $data): string
    
{
        
$output = [];

        
// Description
        
if (!empty($data['description'])) {
            
$output[] = $this->formatDescription($data['description']);
        }

        
// See also
        
if (!empty($data['seeAlso'])) {
            
$output[] = $this->formatSeeAlso($data['seeAlso']);
        }

        return 
\implode("\n\n"\array_filter($output));
    }

    
/**
     * Format a constant entry.
     *
     * @param array $data Constant data
     */
    
private function formatConstant(array $data): string
    
{
        
$output = [];

        if (isset(
$data['value'])) {
            
$output[] = '<strong>Value:</strong> '.$this->thunkTags($data['value']);
        }

        if (!empty(
$data['description'])) {
            
$output[] = $this->formatDescription($data['description']);
        }

        if (!empty(
$data['seeAlso'])) {
            
$output[] = $this->formatSeeAlso($data['seeAlso']);
        }

        return 
\implode("\n\n"\array_filter($output));
    }

    
/**
     * Format a description section.
     *
     * @param string $description Description text with semantic tags
     *
     * @return string Formatted description
     */
    
private function formatDescription(string $description): string
    
{
        
$output = ['<comment>Description:</comment>'];

        
$text $this->thunkTags($description);
        
$wrapped $this->wrapper->wrap($text$this->width 2);

        
$output \array_merge($output$this->indentWrappedLines($wrapped'  '));

        return 
\implode("\n"$output);
    }

    
/**
     * Format parameters section.
     *
     * @param array $params Parameter list
     */
    
private function formatParameters(array $params): string
    
{
        
// Decide layout based on terminal width
        // Use table layout for wide terminals (80+), stacked for narrow
        
if ($this->width >= 80) {
            return 
$this->formatParametersTable($params);
        } else {
            return 
$this->formatParametersStacked($params);
        }
    }

    
/**
     * Format parameters as a table (for wide terminals).
     *
     * @param array $params Parameter list
     */
    
private function formatParametersTable(array $params): string
    
{
        
$output = ['<comment>Param:</comment>'];

        
// Calculate column widths (matching old format)
        
$typeWidth \max(\array_map(function ($param) {
            return 
\mb_strlen($param['type'] ?? 'mixed');
        }, 
$params));

        
$nameWidth \max(\array_map(function ($param) {
            return 
\mb_strlen($param['name']);
        }, 
$params));

        
// Build columns with padding OUTSIDE style tags
        
$indent \str_repeat(' '$typeWidth $nameWidth 6);
        
$wrapWidth $this->width \mb_strlen($indent);

        foreach (
$params as $param) {
            
$type $param['type'] ?? 'mixed';
            
$name $param['name'];
            
$desc $this->thunkTags($param['description'] ?? '');

            
// Wrap in style tags first, THEN pad to avoid long color blocks
            
$typeFormatted '<info>'.$type.'</info>'.\str_repeat(' '$typeWidth \mb_strlen($type));
            
$nameFormatted '<strong>'.$name.'</strong>'.\str_repeat(' '$nameWidth \mb_strlen($name));

            
// Wrap description with proper indentation
            
if (!empty($desc)) {
                
$wrapped $this->wrapper->wrap($desc$wrapWidth);
                
$firstLine '  '.$typeFormatted.'  '.$nameFormatted.'  ';
                
$output \array_merge($output$this->indentWrappedLines($wrapped$indent$firstLine));
            } else {
                
$output[] = '  '.$typeFormatted.'  '.$nameFormatted;
            }
        }

        return 
\implode("\n"$output);
    }

    
/**
     * Format parameters stacked (for narrow terminals).
     *
     * @param array $params Parameter list
     */
    
private function formatParametersStacked(array $params): string
    
{
        
$output = ['<comment>Param:</comment>'];

        
// Calculate type width for alignment
        
$typeWidth \max(\array_map(function ($param) {
            return 
\mb_strlen($param['type'] ?? 'mixed');
        }, 
$params));

        foreach (
$params as $param) {
            
$type \str_pad($param['type'] ?? 'mixed'$typeWidth);
            
$name $param['name'];

            
$output[] = \sprintf('  <info>%s</info>  <strong>%s</strong>'$type$name);

            if (!empty(
$param['description'])) {
                
$desc $this->thunkTags($param['description']);
                
$indent \str_repeat(' '$typeWidth 4);
                
$wrapped $this->wrapper->wrap($desc$this->width \mb_strlen($indent));
                
$output \array_merge($output$this->indentWrappedLines($wrapped$indent));
            }
        }

        return 
\implode("\n"$output);
    }

    
/**
     * Format return value section.
     *
     * @param array $return Return value data
     */
    
private function formatReturn(array $return): string
    
{
        
$output = ['<comment>Return:</comment>'];

        
$type $return['type'] ?? 'unknown';
        
$desc $return['description'] ?? '';

        
$indent \str_repeat(' '\mb_strlen($type) + 4);
        
$wrapWidth $this->width \mb_strlen($indent);

        if (!empty(
$desc)) {
            
$desc $this->thunkTags($desc);
            
$wrapped $this->wrapper->wrap($desc$wrapWidth);
            
$firstLine \sprintf('  <info>%s</info>  '$type);
            
$output \array_merge($output$this->indentWrappedLines($wrapped$indent$firstLine));
        } else {
            
$output[] = \sprintf('  <info>%s</info>'$type);
        }

        return 
\implode("\n"$output);
    }

    
/**
     * Format see also section.
     *
     * @param array $seeAlso List of related functions/classes
     */
    
private function formatSeeAlso(array $seeAlso): string
    
{
        if (empty(
$seeAlso)) {
            return 
'';
        }

        
$output = ['<comment>See Also:</comment>'];

        
// Format items with hyperlinks if manual is available
        
$items \array_map(function ($item) {
            return 
$this->formatSeeAlsoItem($item);
        }, 
$seeAlso);

        
// Don't wrap - console tags need to stay intact
        // Just join with commas and indent
        
$output[] = '  '.\implode(', '$items);

        return 
\implode("\n"$output);
    }

    
/**
     * Format a single see also item with hyperlink if available.
     *
     * @param string $item Function or class name (may contain XML tags)
     */
    
private function formatSeeAlsoItem(string $item): string
    
{
        
// Strip XML tags to get the actual function/class name
        
$cleanItem \strip_tags($item);

        
// Check if this item exists in the manual
        
$href null;
        if (
$this->manual !== null && $this->manual->get($cleanItem) !== null) {
            
$href LinkFormatter::getPhpNetUrl($cleanItem);
        }

        
// Add parentheses to functions (like php.net and old manual format)
        // Items with <function> tags are functions, otherwise classes/constants
        
$displayText $cleanItem;
        if (
\strpos($item'<function>') !== false) {
            
$displayText .= '()';
        }

        if (
$href !== null) {
            return 
LinkFormatter::styleWithHref('info'$displayText$href);
        }

        
// No hyperlink; apply semantic tag formatting, then add parens if function
        
$formatted $this->thunkTags($item);
        if (
\strpos($item'<function>') !== false && \strpos($formatted'()') === false) {
            
$formatted .= '()';
        }

        return 
$formatted;
    }

    
/**
     * Indent wrapped text lines.
     *
     * Takes wrapped text and adds indentation to each line.
     * The first line can have a different prefix than subsequent lines.
     *
     * @param string $wrapped     Wrapped text (may contain newlines)
     * @param string $indent      Indentation for continuation lines
     * @param string $firstIndent Optional different indentation for first line (defaults to $indent)
     *
     * @return array Lines with indentation applied
     */
    
private function indentWrappedLines(string $wrappedstring $indent, ?string $firstIndent null): array
    {
        
$firstIndent $firstIndent ?? $indent;
        
$lines \explode("\n"$wrapped);
        
$output = [];

        foreach (
$lines as $i => $line) {
            
$output[] = ($i === $firstIndent $indent).$line;
        }

        return 
$output;
    }

    
/**
     * Convert semantic XML tags to Symfony Console format tags.
     *
     * @param string $text Text with semantic tags
     *
     * @return string Text with console format tags
     */
    
private function thunkTags(string $text): string
    
{
        
// First, escape any < and > that aren't part of our semantic tags
        // Protect our semantic tags by replacing them with placeholders
        
$tagMap = [];
        
$tagIndex 0;

        
// Protect semantic tags
        
$semanticTags = ['parameter''function''constant''classname''type''literal''class'];
        foreach (
$semanticTags as $tag) {
            
$text \preg_replace_callback(
                
"/<{$tag}>|<\/{$tag}>/",
                function (
$matches) use (&$tagMap, &$tagIndex) {
                    
$placeholder "\x00TAG{$tagIndex}\x00";
                    
$tagMap[$placeholder] = $matches[0];
                    
$tagIndex++;

                    return 
$placeholder;
                },
                
$text
            
);
        }

        
// Now escape any remaining < and > (these are content, not tags)
        
$text \str_replace(['<''>'], ['\\<''\\>'], $text);

        
// Restore protected tags
        
$text \str_replace(\array_keys($tagMap), \array_values($tagMap), $text);

        
// Handle parameters: add $ prefix and make bold
        
$text \preg_replace_callback(
            
'/<parameter>([^<]+)<\/parameter>/',
            function (
$matches) {
                
$name $matches[1];
                
// Add $ if not already present
                
if ($name[0] !== '$') {
                    
$name '$'.$name;
                }

                return 
'<strong>'.$name.'</strong>';
            },
            
$text
        
);

        
// Handle functions: add () suffix and make bold
        
$text \preg_replace_callback(
            
'/<function>([^<]+)<\/function>/',
            function (
$matches) {
                
$name $matches[1];
                
// Add () if not already present
                
if (\substr($name, -2) !== '()') {
                    
$name .= '()';
                }

                return 
'<strong>'.$name.'</strong>';
            },
            
$text
        
);

        
// Map other semantic tags to corresponding formats
        
$replacements = [
            
'<constant>'   => '<info>',
            
'</constant>'  => '</info>',
            
'<classname>'  => '<class>',
            
'</classname>' => '</class>',
            
'<class>'      => '<class>',
            
'</class>'     => '</class>',
            
'<type>'       => '<info>',
            
'</type>'      => '</info>',
            
'<literal>'    => '<return>',
            
'</literal>'   => '</return>',
        ];

        
$text \str_replace(\array_keys($replacements), \array_values($replacements), $text);

        return 
$text;
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

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

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