From 79b5c49ae5b87d81e5b98f3df85762c4cd86cfcc Mon Sep 17 00:00:00 2001 From: Andrii Vasyliev Date: Wed, 18 May 2016 07:26:37 +0000 Subject: [PATCH] inited --- .gitignore | 32 ++++ .hidev/commits.md | 75 +++++++++ .hidev/config.yml | 18 +++ .php_cs | 54 +++++++ .scrutinizer.yml | 9 ++ .travis.yml | 26 ++++ CHANGELOG.md | 48 ++++++ LICENSE | 29 ++++ README.md | 43 ++++++ composer.json | 60 ++++++++ phpunit.xml.dist | 13 ++ src/Helper.php | 140 +++++++++++++++++ src/Plugin.php | 309 ++++++++++++++++++++++++++++++++++++++ tests/_bootstrap.php | 14 ++ tests/composer.json | 13 ++ tests/unit/PluginTest.php | 51 +++++++ 16 files changed, 934 insertions(+) create mode 100644 .gitignore create mode 100644 .hidev/commits.md create mode 100644 .hidev/config.yml create mode 100644 .php_cs create mode 100644 .scrutinizer.yml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/Helper.php create mode 100644 src/Plugin.php create mode 100644 tests/_bootstrap.php create mode 100644 tests/composer.json create mode 100644 tests/unit/PluginTest.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8655935 --- /dev/null +++ b/.gitignore @@ -0,0 +1,32 @@ +# hidev internals +.hidev/composer.json +.hidev/composer.lock +.hidev/vendor + +# IDE & OS files +.*.swp +.DS_Store +.buildpath +.idea +.project +.settings +Thumbs.db +nbproject + +# php-cs-fixer cache +.php_cs.cache + +# vendor dirs +vendor + +# composer lock files +composer.lock + +# phpunit generated files +coverage.clover + +# PHARs +composer.phar +php-cs-fixer.phar +phpunit-skelgen.phar +phpunit.phar diff --git a/.hidev/commits.md b/.hidev/commits.md new file mode 100644 index 0000000..c6d4017 --- /dev/null +++ b/.hidev/commits.md @@ -0,0 +1,75 @@ +hiqdev/composer-config-plugin commits history +--------------------------------------------- + +## 0.1.1 2016-05-11 + +- Fixed: process root package in the last + - 09a97bf 2016-05-11 process root package in the last (sol@hiqdev.com) + +## 0.1.0 2016-04-30 + +- Added creating `vendor/hiqddev/aliases.php` with all found aliases + - 7797466 2016-04-30 csfixed (sol@hiqdev.com) + - e8b5ec4 2016-04-30 renamed `require` to `plugins` (sol@hiqdev.com) + - ee4a3bc 2016-04-30 + creating `vendor/hiqddev/aliases.php` with all aliases (sol@hiqdev.com) + +## 0.0.9 2016-04-15 + +- Removed writing common config + - 4d1db04 2016-04-15 removed writing common-config (sol@hiqdev.com) + - e7072d3 2016-04-15 changed to `common-config` <- `common` (sol@hiqdev.com) + +## 0.0.8 2016-04-15 + + - c1ca12b 2016-04-15 changed package processing condition (sol@hiqdev.com) + +## 0.0.7 2016-04-15 + +- Changed to not touch yii2-composer + - 7fd7dac 2016-04-15 don't touch yii2-composer (sol@hiqdev.com) + +## 0.0.6 2016-04-13 + +- Changed to create separate manageable configs + - 3722bb3 2016-04-13 improved package description (sol@hiqdev.com) + - 9209cbb 2016-04-13 aliases put to `common.php` file (sol@hiqdev.com) + - 5e93ea3 2016-04-13 REDONE to create separate manageable configs (sol@hiqdev.com) + +## 0.0.5 2016-03-30 + +- Changed `yii2-extraconfig` to `extension-config` + - c47dc8f 2016-03-30 + mergeConfig (sol@hiqdev.com) + - 2f03857 2016-03-30 redoing `yii2-extraconfig` to `extension-config` (sol@hiqdev.com) + - a935f20 2016-03-21 trying empty original yii2 `extensions.php` file (sol@hiqdev.com) + +## 0.0.4 2016-03-11 + +- Added processing packages that have extraconfig option + - 006c65f 2016-03-11 rehideved (sol@hiqdev.com) + - 1a949c3 2016-03-11 + process packages that have extraconfig option (sol@hiqdev.com) + - de3f3fa 2016-01-15 fixed tests (sol@hiqdev.com) + +## 0.0.3 2016-01-15 + +- Fixed bug + - 75c9cbf 2016-01-14 fixed stupid typo (sol@hiqdev.com) + +## 0.0.2 2016-01-14 + +- Fixed PHP 5.5 compatibility + - 2b22620 2016-01-14 fixed for PHP 5.5 compatibility (sol@hiqdev.com) + +## 0.0.1 2016-01-14 + +- Added basics + - 71100f2 2016-01-06 fixed (sol@hiqdev.com) + - 8ef495a 2016-01-06 dropped old bootstrap support (sol@hiqdev.com) + - ed7d8b7 2016-01-06 fixes (sol@hiqdev.com) + - c1490d8 2016-01-06 + root package processing and `BASE_DIR_ALIAS` (sol@hiqdev.com) + - 0a48dee 2016-01-06 looks working (sol@hiqdev.com) + - 96e736f 2016-01-06 adding extraconfig (sol@hiqdev.com) + - 03dc968 2016-01-05 fixed (sol@hiqdev.com) + - e38ce2a 2016-01-05 inited (sol@hiqdev.com) + +## Development started 2016-01-05 + diff --git a/.hidev/config.yml b/.hidev/config.yml new file mode 100644 index 0000000..09b65b5 --- /dev/null +++ b/.hidev/config.yml @@ -0,0 +1,18 @@ +package: + type: composer-plugin + name: composer-config-plugin + title: Composer plugin for config assembling + headline: Composer Config Plugin + keywords: composer, config, assembling, plugin + namespace: hiqdev\ComposerConfigPlugin + description: | + This [Composer](https://getcomposer.org/) plugin that provides assembling of configs + and thus providing extendable plugin system. + + - scans installed packages for extra `config-plugin` option in their `composer.json` + - collects and writes params file + - collects and writes config files + +plugins: + hiqdev/hidev-php: "*" + hiqdev/hidev-vendor: "*" diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..6b38401 --- /dev/null +++ b/.php_cs @@ -0,0 +1,54 @@ +setUsingCache(true) + ->level(Symfony\CS\FixerInterface::SYMFONY_LEVEL) + ->fixers([ + '-long_array_syntax', /// Arrays should use the long syntax + '-php4_constructor', /// Convert PHP4-style constructors to __construct. Warning! This could change code behavior + '-phpdoc_var_to_type', /// @var should always be written as @type + '-align_double_arrow', /// Align double arrow symbols in consecutive lines + '-unalign_double_arrow', /// Unalign double arrow symbols in consecutive lines + '-align_equals', /// Align equals symbols in consecutive lines + '-unalign_equals', /// Unalign equals symbols in consecutive lines + '-blankline_after_open_tag', /// Ensure there is no code on the same line as the PHP open tag and it is followed by a blankline + '-phpdoc_no_empty_return', /// @return void and @return null annotations should be omitted from phpdocs + '-empty_return', /// A return statement wishing to return nothing should be simply "return" + '-return', /// An empty line feed should precede a return statement + '-phpdoc_params', /// All items of the @param, @throws, @return, @var, and @type phpdoc tags must be aligned vertically + '-phpdoc_scalar', /// Scalar types should always be written in the same form. "int", not "integer"; "bool", not "boolean" + '-phpdoc_separation', /// Annotations of a different type are separated by a single blank line + '-phpdoc_to_comment', /// Docblocks should only be used on structural elements + 'header_comment', /// Add, replace or remove header comment + 'concat_with_spaces', /// Concatenation should be used with at least one whitespace around + 'ereg_to_preg', /// Replace deprecated ereg regular expression functions with preg. Warning! This could change code behavior + 'multiline_spaces_before_semicolon', /// Multi-line whitespace before closing semicolon are prohibited + 'newline_after_open_tag', /// Ensure there is no code on the same line as the PHP open tag + 'single_blank_line_before_namespace', /// There should be no blank lines before a namespace declaration + 'ordered_use', /// Ordering use statements + 'phpdoc_order', /// Annotations in phpdocs should be ordered so that @param come first, then @throws, then @return + 'pre_increment', /// Pre incrementation/decrementation should be used if possible + 'short_array_syntax', /// PHP arrays should use the PHP 5.4 short-syntax + 'strict', /// Comparison should be strict. Warning! This could change code behavior + 'strict_param', /// Functions should be used with $strict param. Warning! This could change code behavior + ]) + ->finder( + Symfony\CS\Finder\DefaultFinder::create() + ->in(__DIR__) + ->notPath('vendor') + ->notPath('runtime') + ->notPath('web/assets') + ->notPath('tests/unit/UnitTester.php') + ) +; diff --git a/.scrutinizer.yml b/.scrutinizer.yml new file mode 100644 index 0000000..4d60661 --- /dev/null +++ b/.scrutinizer.yml @@ -0,0 +1,9 @@ +checks: + php: + code_rating: true + duplication: true +tools: + php_code_coverage: + enabled: true + external_code_coverage: + timeout: 600 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..250eabb --- /dev/null +++ b/.travis.yml @@ -0,0 +1,26 @@ +language: php +php: + - 5.5 + - 5.6 + - 7 + - hhvm +matrix: + allow_failures: + - + php: hhvm +cache: + directories: + - $HOME/.composer/cache +before_install: + - 'composer self-update' + - 'composer --version' + - 'wget http://hiqdev.com/hidev/hidev.phar -O hidev.phar && chmod a+x hidev.phar' + - './hidev.phar --version' + - './hidev.phar travis/before_install' +sudo: false +install: + - './hidev.phar travis/install' +script: + - './hidev.phar travis/script' +after_script: + - './hidev.phar travis/after_script' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5db906b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +hiqdev/composer-config-plugin changelog +--------------------------------------- + +## 0.1.1 2016-05-11 + +- Fixed: process root package in the last + +## 0.1.0 2016-04-30 + +- Added creating `vendor/hiqddev/aliases.php` with all found aliases + +## 0.0.9 2016-04-15 + +- Removed writing common config + +## 0.0.8 2016-04-15 + + +## 0.0.7 2016-04-15 + +- Changed to not touch yii2-composer + +## 0.0.6 2016-04-13 + +- Changed to create separate manageable configs + +## 0.0.5 2016-03-30 + +- Changed `yii2-extraconfig` to `extension-config` + +## 0.0.4 2016-03-11 + +- Added processing packages that have extraconfig option + +## 0.0.3 2016-01-15 + +- Fixed bug + +## 0.0.2 2016-01-14 + +- Fixed PHP 5.5 compatibility + +## 0.0.1 2016-01-14 + +- Added basics + +## Development started 2016-01-05 + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..84d7b2d --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +Copyright © 2016, HiQDev (http://hiqdev.com/) +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of HiQDev nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8effbf0 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +Composer Config Plugin +====================== + +**Composer plugin for config assembling** + +[![Latest Stable Version](https://poser.pugx.org/hiqdev/composer-config-plugin/v/stable)](https://packagist.org/packages/hiqdev/composer-config-plugin) +[![Total Downloads](https://poser.pugx.org/hiqdev/composer-config-plugin/downloads)](https://packagist.org/packages/hiqdev/composer-config-plugin) +[![Build Status](https://img.shields.io/travis/hiqdev/composer-config-plugin.svg)](https://travis-ci.org/hiqdev/composer-config-plugin) +[![Scrutinizer Code Coverage](https://img.shields.io/scrutinizer/coverage/g/hiqdev/composer-config-plugin.svg)](https://scrutinizer-ci.com/g/hiqdev/composer-config-plugin/) +[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/hiqdev/composer-config-plugin.svg)](https://scrutinizer-ci.com/g/hiqdev/composer-config-plugin/) +[![Dependency Status](https://www.versioneye.com/php/hiqdev:composer-config-plugin/dev-master/badge.svg)](https://www.versioneye.com/php/hiqdev:composer-config-plugin/dev-master) + +This [Composer](https://getcomposer.org/) plugin that provides assembling of configs +and thus providing extendable plugin system. + +- scans installed packages for extra `config-plugin` option in their `composer.json` +- collects and writes params files +- collects and writes config files + +## Installation + +The preferred way to install this composer-plugin is through [composer](http://getcomposer.org/download/). + +Either run + +```sh +php composer.phar require "hiqdev/composer-config-plugin" +``` + +or add + +```json +"hiqdev/composer-config-plugin": "*" +``` + +to the require section of your composer.json. + +## License + +This project is released under the terms of the BSD-3-Clause [license](LICENSE). +Read more [here](http://choosealicense.com/licenses/bsd-3-clause). + +Copyright © 2016, HiQDev (http://hiqdev.com/) diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..ef777c0 --- /dev/null +++ b/composer.json @@ -0,0 +1,60 @@ +{ + "name": "hiqdev/composer-config-plugin", + "type": "composer-plugin", + "description": "Composer plugin for config assembling", + "keywords": [ + "composer", + "config", + "assembling", + "plugin" + ], + "homepage": "https://github.com/hiqdev/composer-config-plugin", + "license": "BSD-3-Clause", + "support": { + "email": "support@hiqdev.com", + "source": "https://github.com/hiqdev/composer-config-plugin", + "issues": "https://github.com/hiqdev/composer-config-plugin/issues", + "wiki": "https://github.com/hiqdev/composer-config-plugin/wiki", + "forum": "http://forum.hiqdev.com/" + }, + "authors": [ + { + "name": "Andrii Vasyliev", + "role": "Project lead", + "email": "sol@hiqdev.com", + "homepage": "http://hipanel.com/" + }, + { + "name": "Dmitry Naumenko", + "role": "Lead backend developer", + "email": "silverfire@hiqdev.com", + "homepage": "http://silverfire.me/" + }, + { + "name": "Andrey Klochok", + "role": "Lead frontend developer", + "email": "tafid@hiqdev.com", + "homepage": "http://hiqdev.com/" + }, + { + "name": "Yuriy Myronchuk", + "role": "QA Lead", + "email": "bladeroot@hiqdev.com", + "homepage": "http://hiqdev.com/" + } + ], + "require": { + "composer-plugin-api": "^1.0" + }, + "require-dev": { + "composer/composer": "~1.0@dev" + }, + "autoload": { + "psr-4": { + "hiqdev\\ComposerConfigPlugin\\": "src" + } + }, + "extra": { + "class": "hiqdev\\ComposerConfigPlugin\\Plugin" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..60413df --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,13 @@ + + + + + ./tests/unit/ + + + + + ./src/ + + + diff --git a/src/Helper.php b/src/Helper.php new file mode 100644 index 0000000..2130324 --- /dev/null +++ b/src/Helper.php @@ -0,0 +1,140 @@ + + */ +class Helper +{ + /** + * Merges two or more arrays into one recursively. + * Based on Yii2 yii\helpers\BaseArrayHelper::merge. + * @param array $a array to be merged to + * @param array $b array to be merged from + * @return array the merged array + */ + public static function mergeConfig($a, $b) + { + $args = func_get_args(); + $res = array_shift($args); + foreach ($args as $items) { + if (!is_array($items)) { + continue; + } + foreach ($items as $k => $v) { + if (is_int($k)) { + if (isset($res[$k])) { + $res[] = $v; + } else { + $res[$k] = $v; + } + } elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) { + $res[$k] = self::mergeConfig($res[$k], $v); + } else { + $res[$k] = $v; + } + } + } + + return $res; + } + + /** + * Dumps closure object to string. + * Based on http://www.metashock.de/2013/05/dump-source-code-of-closure-in-php/. + * @param Closure $c + * @return string + */ + public static function dumpClosure(Closure $c) + { + $res = 'function ('; + $fun = new ReflectionFunction($c); + $args = []; + foreach ($fun->getParameters() as $arg) { + $str = ''; + if ($arg->isArray()) { + $str .= 'array '; + } elseif ($arg->getClass()) { + $str .= $arg->getClass()->name . ' '; + } + if ($arg->isPassedByReference()) { + $str .= '&'; + } + $str .= '$' . $arg->name; + if ($arg->isOptional()) { + $str .= ' = ' . var_export($arg->getDefaultValue(), true); + } + $args[] = $str; + } + $res .= implode(', ', $args); + $res .= ') {' . PHP_EOL; + $lines = file($fun->getFileName()); + for ($i = $fun->getStartLine(); $i < $fun->getEndLine(); ++$i) { + $res .= $lines[$i]; + } + + return rtrim($res, "\n ,"); + } + + /** + * Returns a parsable string representation of given value. + * In contrast to var_dump outputs Closures as PHP code. + * @param mixed $value + * @return string + */ + public static function exportVar($value) + { + $closures = self::collectClosures($value); + $res = var_export($value, true); + if (!empty($closures)) { + $subs = []; + foreach ($closures as $key => $closure) { + $subs["'" . $key . "'"] = self::dumpClosure($closure); + } + $res = strtr($res, $subs); + } + + return $res; + } + + /** + * Collects closures from given input. + * Substitutes closures with a tag. + * @param mixed $input will be changed + * @return array array of found closures + */ + private static function collectClosures(&$input) + { + static $closureNo = 1; + $closures = []; + if (is_array($input)) { + foreach ($input as &$value) { + if (is_array($value) || $value instanceof Closure) { + $closures = array_merge($closures, self::collectClosures($value)); + } + } + } elseif ($input instanceof Closure) { + ++$closureNo; + $key = "--==<<[[((Closure#$closureNo))]]>>==--"; + $closures[$key] = $input; + $input = $key; + } + + return $closures; + } +} diff --git a/src/Plugin.php b/src/Plugin.php new file mode 100644 index 0000000..af79103 --- /dev/null +++ b/src/Plugin.php @@ -0,0 +1,309 @@ + + */ +class Plugin implements PluginInterface, EventSubscriberInterface +{ + const PACKAGE_TYPE = 'yii2-extension'; + const EXTRA_OPTION_NAME = 'extension-plugin'; + const OUTPUT_PATH = 'hiqdev'; + const BASE_DIR_SAMPLE = ''; + const VENDOR_DIR_SAMPLE = '/vendor'; + + /** + * @var PackageInterface[] the array of active composer packages + */ + protected $packages; + + /** + * @var string absolute path to the package base directory. + */ + protected $baseDir; + + /** + * @var string absolute path to vendor directory. + */ + protected $vendorDir; + + /** + * @var Filesystem utility + */ + protected $filesystem; + + /** + * @var array whole data + */ + protected $data = [ + 'aliases' => [], + 'extensions' => [], + ]; + + /** + * @var Composer instance + */ + protected $composer; + + /** + * @var IOInterface + */ + public $io; + + /** + * Initializes the plugin object with the passed $composer and $io. + * @param Composer $composer + * @param IOInterface $io + */ + public function activate(Composer $composer, IOInterface $io) + { + $this->composer = $composer; + $this->io = $io; + } + + /** + * Returns list of events the plugin is subscribed to. + * @return array list of events + */ + public static function getSubscribedEvents() + { + return [ + ScriptEvents::POST_AUTOLOAD_DUMP => [ + ['onPostAutoloadDump', 0], + ], + ]; + } + + /** + * Simply rewrites extensions file from scratch. + * @param Event $event + */ + public function onPostAutoloadDump(Event $event) + { + $this->io->writeError('Generating extensions files'); + foreach ($this->getPackages() as $package) { + if ($package instanceof \Composer\Package\CompletePackageInterface) { + $this->processPackage($package); + } + } + $this->processPackage($this->composer->getPackage()); + + foreach ($this->data as $name => $data) { + $this->saveFile($this->buildOutputPath($name), $data); + } + } + + public function buildOutputPath($name) + { + return static::OUTPUT_PATH . DIRECTORY_SEPARATOR . $name . '.php'; + } + + /** + * Writes file. + * @param string $file + * @param array $data + */ + protected function saveFile($file, array $data) + { + $path = $this->getVendorDir() . '/' . $file; + if (!file_exists(dirname($path))) { + mkdir(dirname($path), 0777, true); + } + $array = str_replace("'" . self::BASE_DIR_SAMPLE, '$baseDir . \'', Helper::exportVar($data)); + file_put_contents($path, "getExtra(); + $files = isset($extra[self::EXTRA_OPTION_NAME]) ? $extra[self::EXTRA_OPTION_NAME] : null; + if ($package->getType() !== self::PACKAGE_TYPE && is_null($files)) { + return; + } + + $extension = [ + 'name' => $package->getName(), + 'version' => $package->getVersion(), + ]; + if ($package->getVersion() === '9999999-dev') { + $reference = $package->getSourceReference() ?: $package->getDistReference(); + if ($reference) { + $extension['reference'] = $reference; + } + } + $this->data['extensions'][$package->getName()] = $extension; + + $aliases = array_merge( + $this->prepareAliases($package, 'psr-0'), + $this->prepareAliases($package, 'psr-4') + ); + $this->data['aliases'] = array_merge($this->data['aliases'], $aliases); + foreach ((array) $files as $name => $path) { + $config = $this->readExtensionConfig($package, $path); + $config['aliases'] = array_merge( + $aliases, + isset($config['aliases']) ? (array) $config['aliases'] : [] + ); + $this->data['aliases'] = array_merge($this->data['aliases'], $config['aliases']); + $this->data[$name] = isset($this->data[$name]) ? Helper::mergeConfig($this->data[$name], $config) : $config; + } + } + + /** + * Read extra config. + * @param string $file + * @return array + */ + protected function readExtensionConfig(PackageInterface $package, $file) + { + $path = $this->preparePath($package, $file); + if (!file_exists($path)) { + $this->io->writeError('Non existent extension config file ' . $file . ' in ' . $package->getName()); + exit(1); + } + return require $path; + } + + /** + * Prepare aliases. + * + * @param PackageInterface $package + * @param string 'psr-0' or 'psr-4' + * @return array + */ + protected function prepareAliases(PackageInterface $package, $psr) + { + $autoload = $package->getAutoload(); + if (empty($autoload[$psr])) { + return []; + } + + $aliases = []; + foreach ($autoload[$psr] as $name => $path) { + if (is_array($path)) { + // ignore psr-4 autoload specifications with multiple search paths + // we can not convert them into aliases as they are ambiguous + continue; + } + $name = str_replace('\\', '/', trim($name, '\\')); + $path = $this->preparePath($package, $path); + $path = $this->substitutePath($path, $this->getBaseDir(), self::BASE_DIR_SAMPLE); + if ('psr-0' === $psr) { + $path .= '/' . $name; + } + $aliases["@$name"] = $path; + } + + return $aliases; + } + + /** + * Substitute path with alias if applicable. + * @param string $path + * @param string $dir + * @param string $alias + * @return string + */ + public function substitutePath($path, $dir, $alias) + { + return (substr($path, 0, strlen($dir) + 1) === $dir . '/') ? $alias . substr($path, strlen($dir)) : $path; + } + + public function preparePath(PackageInterface $package, $path) + { + if (!$this->getFilesystem()->isAbsolutePath($path)) { + $prefix = $package instanceof RootPackageInterface ? $this->getBaseDir() : $this->getVendorDir() . '/' . $package->getPrettyName(); + $path = $prefix . '/' . $path; + } + + return $this->getFilesystem()->normalizePath($path); + } + + /** + * Sets [[packages]]. + * @param PackageInterface[] $packages + */ + public function setPackages(array $packages) + { + $this->packages = $packages; + } + + /** + * Gets [[packages]]. + * @return \Composer\Package\PackageInterface[] + */ + public function getPackages() + { + if ($this->packages === null) { + $this->packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages(); + } + + return $this->packages; + } + + /** + * Get absolute path to package base dir. + * @return string + */ + public function getBaseDir() + { + if ($this->baseDir === null) { + $this->baseDir = dirname($this->getVendorDir()); + } + + return $this->baseDir; + } + + /** + * Get absolute path to composer vendor dir. + * @return string + */ + public function getVendorDir() + { + if ($this->vendorDir === null) { + $dir = $this->composer->getConfig()->get('vendor-dir', '/'); + $this->vendorDir = $this->getFilesystem()->normalizePath($dir); + } + + return $this->vendorDir; + } + + /** + * Getter for filesystem utility. + * @return Filesystem + */ + public function getFilesystem() + { + if ($this->filesystem === null) { + $this->filesystem = new Filesystem(); + } + + return $this->filesystem; + } +} diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php new file mode 100644 index 0000000..ec107b6 --- /dev/null +++ b/tests/_bootstrap.php @@ -0,0 +1,14 @@ +composer = new Composer(); + $this->composer->setConfig(new Config(true, getcwd())); + $this->io = $this->getMock('Composer\IO\IOInterface'); + $this->event = $this->getMock('Composer\Script\Event', [], ['test', $this->composer, $this->io]); + + $this->object = new Plugin(); + $this->object->setPackages($this->packages); + $this->object->activate($this->composer, $this->io); + } + + public function testGetPackages() + { + $this->assertSame($this->packages, $this->object->getPackages()); + } + + public function testGetSubscribedEvents() + { + $this->assertInternalType('array', $this->object->getSubscribedEvents()); + } +}