Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. BinaryInstaller.php

function BinaryInstaller::generateUnixyProxyCode

1 call to BinaryInstaller::generateUnixyProxyCode()
BinaryInstaller::installUnixyProxyBinaries in vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php

File

vendor/composer/composer/src/Composer/Installer/BinaryInstaller.php, line 209

Class

BinaryInstaller
Utility to handle installation of package "bin"/binaries

Namespace

Composer\Installer

Code

protected function generateUnixyProxyCode(string $bin, string $link) : string {
    $binPath = $this->filesystem
        ->findShortestPath($link, $bin);
    $binDir = ProcessExecutor::escape(dirname($binPath));
    $binFile = basename($binPath);
    $binContents = (string) file_get_contents($bin, false, null, 0, 500);
    // For php files, we generate a PHP proxy instead of a shell one,
    // which allows calling the proxy with a custom php process
    if (Preg::isMatch('{^(#!.*\\r?\\n)?[\\r\\n\\t ]*<\\?php}', $binContents, $match)) {
        // carry over the existing shebang if present, otherwise add our own
        $proxyCode = $match[1] === null ? '#!/usr/bin/env php' : trim($match[1]);
        $binPathExported = $this->filesystem
            ->findShortestPathCode($link, $bin, false, true);
        $streamProxyCode = $streamHint = '';
        $globalsCode = '$GLOBALS[\'_composer_bin_dir\'] = __DIR__;' . "\n";
        $phpunitHack1 = $phpunitHack2 = '';
        // Don't expose autoload path when vendor dir was not set in custom installers
        if ($this->vendorDir !== null) {
            // ensure comparisons work accurately if the CWD is a symlink, as $link is realpath'd already
            $vendorDirReal = realpath($this->vendorDir);
            if ($vendorDirReal === false) {
                $vendorDirReal = $this->vendorDir;
            }
            $globalsCode .= '$GLOBALS[\'_composer_autoload_path\'] = ' . $this->filesystem
                ->findShortestPathCode($link, $vendorDirReal . '/autoload.php', false, true) . ";\n";
        }
        // Add workaround for PHPUnit process isolation
        if ($this->filesystem
            ->normalizePath($bin) === $this->filesystem
            ->normalizePath($this->vendorDir . '/phpunit/phpunit/phpunit')) {
            // workaround issue on PHPUnit 6.5+ running on PHP 8+
            $globalsCode .= '$GLOBALS[\'__PHPUNIT_ISOLATION_EXCLUDE_LIST\'] = $GLOBALS[\'__PHPUNIT_ISOLATION_BLACKLIST\'] = array(realpath(' . $binPathExported . '));' . "\n";
            // workaround issue on all PHPUnit versions running on PHP <8
            $phpunitHack1 = "'phpvfscomposer://'.";
            $phpunitHack2 = '
                $data = str_replace(\'__DIR__\', var_export(dirname($this->realpath), true), $data);
                $data = str_replace(\'__FILE__\', var_export($this->realpath, true), $data);';
        }
        if (trim($match[0]) !== '<?php') {
            $streamHint = ' using a stream wrapper to prevent the shebang from being output on PHP<8' . "\n *";
            $streamProxyCode = <<<STREAMPROXY
if (PHP_VERSION_ID < 80000) {
    if (!class_exists('Composer\\BinProxyWrapper')) {
        /**
         * @internal
         */
        final class BinProxyWrapper
        {
            private \$handle;
            private \$position;
            private \$realpath;

            public function stream_open(\$path, \$mode, \$options, &\$opened_path)
            {
                // get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
                \$opened_path = substr(\$path, 17);
                \$this->realpath = realpath(\$opened_path) ?: \$opened_path;
                \$opened_path = {<span class="php-variable">$phpunitHack1</span>}\$this->realpath;
                \$this->handle = fopen(\$this->realpath, \$mode);
                \$this->position = 0;

                return (bool) \$this->handle;
            }

            public function stream_read(\$count)
            {
                \$data = fread(\$this->handle, \$count);

                if (\$this->position === 0) {
                    \$data = preg_replace('{^#!.*\\r?\\n}', '', \$data);
                }{<span class="php-variable">$phpunitHack2</span>}

                \$this->position += strlen(\$data);

                return \$data;
            }

            public function stream_cast(\$castAs)
            {
                return \$this->handle;
            }

            public function stream_close()
            {
                fclose(\$this->handle);
            }

            public function stream_lock(\$operation)
            {
                return \$operation ? flock(\$this->handle, \$operation) : true;
            }

            public function stream_seek(\$offset, \$whence)
            {
                if (0 === fseek(\$this->handle, \$offset, \$whence)) {
                    \$this->position = ftell(\$this->handle);
                    return true;
                }

                return false;
            }

            public function stream_tell()
            {
                return \$this->position;
            }

            public function stream_eof()
            {
                return feof(\$this->handle);
            }

            public function stream_stat()
            {
                return array();
            }

            public function stream_set_option(\$option, \$arg1, \$arg2)
            {
                return true;
            }

            public function url_stat(\$path, \$flags)
            {
                \$path = substr(\$path, 17);
                if (file_exists(\$path)) {
                    return stat(\$path);
                }

                return false;
            }
        }
    }

    if (
        (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
        || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper'))
    ) {
        return include("phpvfscomposer://" . {<span class="php-variable">$binPathExported</span>});
    }
}

STREAMPROXY;
        }
        return $proxyCode . "\n" . <<<PROXY
<?php

/**
 * Proxy PHP file generated by Composer
 *
 * This file includes the referenced bin path ({<span class="php-variable">$binPath</span>})
 *{<span class="php-variable">$streamHint</span>}
 * @generated
 */

namespace Composer;

{<span class="php-variable">$globalsCode</span>}
{<span class="php-variable">$streamProxyCode</span>}
return include {<span class="php-variable">$binPathExported</span>};

PROXY;
    }
    return <<<PROXY
#!/usr/bin/env sh

# Support bash to support `source` with fallback on \$0 if this does not run with bash
# https://stackoverflow.com/a/35006505/6512
selfArg="\$BASH_SOURCE"
if [ -z "\$selfArg" ]; then
    selfArg="\$0"
fi

self=\$(realpath \$selfArg 2> /dev/null)
if [ -z "\$self" ]; then
    self="\$selfArg"
fi

dir=\$(cd "\${self%[/\\\\]*}" > /dev/null; cd {<span class="php-variable">$binDir</span>} && pwd)

if [ -d /proc/cygdrive ]; then
    case \$(which php) in
        \$(readlink -n /proc/cygdrive)/*)
            # We are in Cygwin using Windows php, so the path must be translated
            dir=\$(cygpath -m "\$dir");
            ;;
    esac
fi

export COMPOSER_RUNTIME_BIN_DIR="\$(cd "\${self%[/\\\\]*}" > /dev/null; pwd)"

# If bash is sourcing this file, we have to source the target as well
bashSource="\$BASH_SOURCE"
if [ -n "\$bashSource" ]; then
    if [ "\$bashSource" != "\$0" ]; then
        source "\${dir}/{<span class="php-variable">$binFile</span>}" "\$@"
        return
    fi
fi

exec "\${dir}/{<span class="php-variable">$binFile</span>}" "\$@"

PROXY;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal