Seditio Source
Root |
./othercms/croogo-4.0.7/vendor/cakephp/plugin-installer/src/Installer/PluginInstaller.php
<?php
namespace Cake\Composer\Installer;

use
Composer\Composer;
use
Composer\Installer\LibraryInstaller;
use
Composer\IO\IOInterface;
use
Composer\Package\PackageInterface;
use
Composer\Repository\InstalledRepositoryInterface;
use
Composer\Script\Event;
use
Composer\Util\Filesystem;
use
RuntimeException;

class
PluginInstaller extends LibraryInstaller
{
   
/**
     * A flag to check usage - once
     *
     * @var bool
     */
   
protected static $checkUsage = true;

   
/**
     * Check usage upon construction
     *
     * @param IOInterface $io composer object
     * @param Composer    $composer composer object
     * @param string      $type what are we loading
     * @param Filesystem  $filesystem composer object
     */
   
public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null)
    {
       
parent::__construct($io, $composer, $type, $filesystem);
       
$this->checkUsage($composer);
    }

   
/**
     * Check that the root composer.json file use the post-autoload-dump hook
     *
     * If not, warn the user they need to update their application's composer file.
     * Do nothing if the main project is not a project (if it's a plugin in development).
     *
     * @param Composer $composer object
     * @return void
     */
   
public function checkUsage(Composer $composer)
    {
        if (static::
$checkUsage === false) {
            return;
        }
        static::
$checkUsage = false;

       
$package = $composer->getPackage();

        if (!
$package || $package->getType() !== 'project') {
            return;
        }

       
$scripts = $composer->getPackage()->getScripts();
       
$postAutoloadDump = 'Cake\Composer\Installer\PluginInstaller::postAutoloadDump';
        if (!isset(
$scripts['post-autoload-dump']) ||
            !
in_array($postAutoloadDump, $scripts['post-autoload-dump'])
        ) {
           
$this->warnUser(
               
'Action required!',
               
'The CakePHP plugin installer has been changed, please update your' .
               
' application composer.json file to add the post-autoload-dump hook.' .
               
' See the changes in https://github.com/cakephp/app/pull/216 for more' .
               
' info.'
           
);
        }
    }

   
/**
     * Warn the developer of action they need to take
     *
     * @param string $title Warning title
     * @param string $text warning text
     *
     * @return void
     */
   
public function warnUser($title, $text)
    {
       
$wrap = function ($text, $width = 75) {
            return
'<error>     ' . str_pad($text, $width) . '</error>';
        };

       
$messages = [
           
'',
           
'',
           
$wrap(''),
           
$wrap($title),
           
$wrap(''),
        ];

       
$lines = explode("\n", wordwrap($text, 68));
        foreach (
$lines as $line) {
           
$messages[] = $wrap($line);
        }

       
$messages = array_merge($messages, [$wrap(''), '', '']);

       
$this->io->write($messages);
    }

   
/**
     * Called whenever composer (re)generates the autoloader
     *
     * Recreates CakePHP's plugin path map, based on composer information
     * and available app-plugins.
     *
     * @param Event $event the composer event object
     * @return void
     */
   
public static function postAutoloadDump(Event $event)
    {
       
$composer = $event->getComposer();
       
$config = $composer->getConfig();

       
$vendorDir = realpath($config->get('vendor-dir'));

       
$packages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
       
$extra = $event->getComposer()->getPackage()->getExtra();
        if (empty(
$extra['plugin-paths'])) {
           
$pluginsDir = dirname($vendorDir) . DIRECTORY_SEPARATOR . 'plugins';
        } else {
           
$pluginsDir = $extra['plugin-paths'];
        }

       
$plugins = static::determinePlugins($packages, $pluginsDir, $vendorDir);

       
$configFile = static::_configFile($vendorDir);
        static::
writeConfigFile($configFile, $plugins);
    }

   
/**
     * Find all plugins available
     *
     * Add all composer packages of type cakephp-plugin, and all plugins located
     * in the plugins directory to a plugin-name indexed array of paths
     *
     * @param array $packages an array of \Composer\Package\PackageInterface objects
     * @param string|array $pluginsDir the path to the plugins dir
     * @param string $vendorDir the path to the vendor dir
     * @return array plugin-name indexed paths to plugins
     */
   
public static function determinePlugins($packages, $pluginsDir = 'plugins', $vendorDir = 'vendor')
    {
       
$plugins = [];

        foreach (
$packages as $package) {
            if (
$package->getType() !== 'cakephp-plugin') {
                continue;
            }

           
$ns = static::primaryNamespace($package);
           
$path = $vendorDir . DIRECTORY_SEPARATOR . $package->getPrettyName();
           
$plugins[$ns] = $path;
        }

        foreach ((array)
$pluginsDir as $path) {
           
$path = static::fullpath($path, $vendorDir);
            if (
is_dir($path)) {
               
$dir = new \DirectoryIterator($path);
                foreach (
$dir as $info) {
                    if (!
$info->isDir() || $info->isDot()) {
                        continue;
                    }

                   
$name = $info->getFilename();
                    if (
$name[0] === '.') {
                        continue;
                    }

                   
$plugins[$name] = $path . DIRECTORY_SEPARATOR . $name;
                }
            }
        }

       
ksort($plugins);

        return
$plugins;
    }

   
/**
     * Turns relative paths in full paths.
     *
     * @param string $path Path
     * @param string $vendorDir The path to the vendor dir
     * @return string
     */
   
protected static function fullpath($path, $vendorDir)
    {
        if (
preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
            return
rtrim($path, '/');
        }

        if (
substr($path, 0, 2) === './') {
           
$path = substr($path, 2);
        }

        return
rtrim(dirname($vendorDir) . DIRECTORY_SEPARATOR . $path);
    }

   
/**
     * Rewrite the config file with a complete list of plugins
     *
     * @param string $configFile the path to the config file
     * @param array $plugins of plugins
     * @param string|null $root The root directory. Defaults to a value generated from $configFile
     * @return void
     */
   
public static function writeConfigFile($configFile, $plugins, $root = null)
    {
       
$root = $root ?: dirname(dirname($configFile));

       
$data = [];
        foreach (
$plugins as $name => $pluginPath) {
           
// Normalize to *nix paths.
           
$pluginPath = str_replace('\\', '/', $pluginPath);
           
$pluginPath .= '/';

           
$pluginPath = str_replace(
               
DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR,
               
DIRECTORY_SEPARATOR,
               
$pluginPath
           
);

           
// Namespaced plugins should use /
           
$name = str_replace('\\', '/', $name);

           
$data[] = sprintf("        '%s' => '%s'", $name, $pluginPath);
        }

       
$data = implode(",\n", $data);

       
$contents = <<<'PHP'
<?php
$baseDir = dirname(dirname(__file__));
return [
    'plugins' => [
%s
    ]
];
PHP;
       
$contents = sprintf($contents, $data);

       
// Gross hacks to work around composer smashing `__FILE__` in this
        // PHP file when it runs the code through eval()
       
$uppercase = function ($matches) {
            return
strtoupper($matches[0]);
        };
       
$contents = preg_replace_callback('/__file__/', $uppercase, $contents);

       
$root = str_replace(
           
DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR,
           
DIRECTORY_SEPARATOR,
           
$root
       
);

       
// Normalize to *nix paths.
       
$root = str_replace('\\', '/', $root);
       
$contents = str_replace('\'' . $root, '$baseDir . \'', $contents);

       
file_put_contents($configFile, $contents);
    }

   
/**
     * Path to the plugin config file
     *
     * @param string $vendorDir path to composer-vendor dir
     * @return string absolute file path
     */
   
protected static function _configFile($vendorDir)
    {
        return
$vendorDir . DIRECTORY_SEPARATOR . 'cakephp-plugins.php';
    }

   
/**
     * Get the primary namespace for a plugin package.
     *
     * @param \Composer\Package\PackageInterface $package composer object
     * @return string The package's primary namespace.
     * @throws \RuntimeException When the package's primary namespace cannot be determined.
     */
   
public static function primaryNamespace($package)
    {
       
$primaryNs = null;
       
$autoLoad = $package->getAutoload();
        foreach (
$autoLoad as $type => $pathMap) {
            if (
$type !== 'psr-4') {
                continue;
            }
           
$count = count($pathMap);

            if (
$count === 1) {
               
$primaryNs = key($pathMap);
                break;
            }

           
$matches = preg_grep('#^(\./)?src/?$#', $pathMap);
            if (
$matches) {
               
$primaryNs = key($matches);
                break;
            }

            foreach ([
'', '.'] as $path) {
               
$key = array_search($path, $pathMap, true);
                if (
$key !== false) {
                   
$primaryNs = $key;
                }
            }
            break;
        }

        if (!
$primaryNs) {
            throw new
RuntimeException(
               
sprintf(
                   
"Unable to get primary namespace for package %s." .
                   
"\nEnsure you have added proper 'autoload' section to your plugin's config" .
                   
" as stated in README on https://github.com/cakephp/plugin-installer",
                   
$package->getName()
                )
            );
        }

        return
trim($primaryNs, '\\');
    }

   
/**
     * Decides if the installer supports the given type.
     *
     * This installer only supports package of type 'cakephp-plugin'.
     *
     * @return bool
     */
   
public function supports($packageType)
    {
        return
'cakephp-plugin' === $packageType;
    }

   
/**
     * Installs specific plugin.
     *
     * After the plugin is installed, app's `cakephp-plugins.php` config file is updated with
     * plugin namespace to path mapping.
     *
     * @param \Composer\Repository\InstalledRepositoryInterface $repo Repository in which to check.
     * @param \Composer\Package\PackageInterface $package Package instance.
     * @deprecated superceeded by the post-autoload-dump hook
     */
   
public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
       
parent::install($repo, $package);
       
$path = $this->getInstallPath($package);
       
$ns = static::primaryNamespace($package);
       
$this->updateConfig($ns, $path);
    }

   
/**
     * Updates specific plugin.
     *
     * After the plugin is installed, app's `cakephp-plugins.php` config file is updated with
     * plugin namespace to path mapping.
     *
     * @param \Composer\Repository\InstalledRepositoryInterface $repo Repository in which to check.
     * @param \Composer\Package\PackageInterface $initial Already installed package version.
     * @param \Composer\Package\PackageInterface $target Updated version.
     * @deprecated superceeded by the post-autoload-dump hook
     *
     * @throws \InvalidArgumentException if $initial package is not installed
     */
   
public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
    {
       
parent::update($repo, $initial, $target);

       
$ns = static::primaryNamespace($initial);
       
$this->updateConfig($ns, null);

       
$path = $this->getInstallPath($target);
       
$ns = static::primaryNamespace($target);
       
$this->updateConfig($ns, $path);
    }

   
/**
     * Uninstalls specific package.
     *
     * @param \Composer\Repository\InstalledRepositoryInterface $repo Repository in which to check.
     * @param \Composer\Package\PackageInterface $package Package instance.
     * @deprecated superceeded by the post-autoload-dump hook
     */
   
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
    {
       
parent::uninstall($repo, $package);
       
$path = $this->getInstallPath($package);
       
$ns = static::primaryNamespace($package);
       
$this->updateConfig($ns, null);
    }

   
/**
     * Update the plugin path for a given package.
     *
     * @param string $name The plugin name being installed.
     * @param string $path The path, the plugin is being installed into.
     */
   
public function updateConfig($name, $path)
    {
       
$name = str_replace('\\', '/', $name);
       
$configFile = static::_configFile($this->vendorDir);
       
$this->_ensureConfigFile($configFile);

       
$return = include $configFile;
        if (
is_array($return) && empty($config)) {
           
$config = $return;
        }
        if (!isset(
$config)) {
           
$this->io->write(
               
'ERROR - `vendor/cakephp-plugins.php` file is invalid. ' .
               
'Plugin path configuration not updated.'
           
);

            return;
        }
        if (!isset(
$config['plugins'])) {
           
$config['plugins'] = [];
        }
        if (
$path == null) {
            unset(
$config['plugins'][$name]);
        } else {
           
$config['plugins'][$name] = $path;
        }
       
$root = dirname($this->vendorDir);
        static::
writeConfigFile($configFile, $config['plugins'], $root);
    }

   
/**
     * Ensure that the vendor/cakephp-plugins.php file exists.
     *
     * If config/plugins.php is found - copy it to the vendor folder
     *
     * @param string $path the config file path.
     * @return void
     */
   
protected function _ensureConfigFile($path)
    {
        if (
file_exists($path)) {
            if (
$this->io->isVerbose()) {
               
$this->io->write('vendor/cakephp-plugins.php exists.');
            }

            return;
        }

       
$oldPath = dirname(dirname($path)) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'plugins.php';
        if (
file_exists($oldPath)) {
           
copy($oldPath, $path);
            if (
$this->io->isVerbose()) {
               
$this->io->write('config/plugins.php found and copied to vendor/cakephp-plugins.php.');
            }

            return;
        }

        if (!
is_dir(dirname($path))) {
           
mkdir(dirname($path));
        }
       
$root = dirname($this->vendorDir);
        static::
writeConfigFile($path, [], $root);

        if (
$this->io->isVerbose()) {
           
$this->io->write('Created vendor/cakephp-plugins.php');
        }
    }
}