├── EmbeddedComposerAwareInterface.php
├── composer.json
├── LICENSE
├── Script.php
├── EmbeddedComposerInterface.php
├── EmbeddedComposer.php
└── EmbeddedComposerBuilder.php
/EmbeddedComposerAwareInterface.php:
--------------------------------------------------------------------------------
1 |
18 | */
19 | interface EmbeddedComposerAwareInterface
20 | {
21 | /**
22 | * Embedded Composer.
23 | *
24 | * @return EmbeddedComposer
25 | */
26 | public function getEmbeddedComposer();
27 | }
28 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dflydev/embedded-composer-core",
3 | "description": "Embed Composer core",
4 | "keywords": ["embedded", "composer", "extensibility"],
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Dragonfly Development Inc.",
9 | "email": "info@dflydev.com",
10 | "homepage": "http://dflydev.com"
11 | },
12 | {
13 | "name": "Beau Simensen",
14 | "email": "beau@dflydev.com",
15 | "homepage": "http://beausimensen.com"
16 | }
17 | ],
18 | "require": {
19 | "php": ">=5.3.2",
20 | "composer/composer": "1.0.*@dev",
21 | "seld/jsonlint": "1.*",
22 |
23 | "symfony/console": "~2.3@dev"
24 | },
25 | "autoload": {
26 | "psr-0": { "Dflydev\\EmbeddedComposer\\Core": "" }
27 | },
28 | "target-dir": "Dflydev/EmbeddedComposer/Core",
29 | "extra": {
30 | "branch-alias": {
31 | "dev-master": "1.0-dev"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012-2014 Dragonfly Development Inc.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is furnished
8 | to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Script.php:
--------------------------------------------------------------------------------
1 |
22 | */
23 | class Script
24 | {
25 | public static function postAutoloadDump(Event $event)
26 | {
27 | $io = $event->getIO();
28 | $composer = $event->getComposer();
29 | $package = $composer->getPackage();
30 | $config = $composer->getConfig();
31 | $filename = $config->get('vendor-dir').'/dflydev/embedded-composer/.root_package.json';
32 | $io->write('Adding '.$package->getName().' ('.$package->getPrettyVersion().') to '.$filename);
33 | $jsonFile = new JsonFile($filename);
34 | $repository = new InstalledFilesystemRepository($jsonFile);
35 | $repository->addPackage(clone $package);
36 | $repository->write();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/EmbeddedComposerInterface.php:
--------------------------------------------------------------------------------
1 |
21 | */
22 | interface EmbeddedComposerInterface
23 | {
24 | /**
25 | * Get the active class loader (may be internal or external)
26 | *
27 | * @return mixed
28 | */
29 | public function getClassLoader();
30 |
31 | /**
32 | * Find a package by name
33 | *
34 | * @param string $name Package name
35 | *
36 | * @return \Composer\Package\PackageInterface
37 | */
38 | public function findPackage($name);
39 |
40 | /**
41 | * Process any additional external Composer autoloader definitions
42 | */
43 | public function processAdditionalAutoloads();
44 |
45 | /**
46 | * Create a Composer instance
47 | *
48 | * @param IOInterface $io IO
49 | *
50 | * @return \Composer\Composer
51 | */
52 | public function createComposer(IOInterface $io);
53 |
54 | /**
55 | * Create an Installer instance
56 | *
57 | * @param IOInterface $io
58 | */
59 | public function createInstaller(IOInterface $io);
60 |
61 | /**
62 | * Get a repository repository representing the external repository and
63 | * the internal repository if it exists.
64 | *
65 | * @return \Composer\Repository\RepositoryInterface
66 | */
67 | public function getRepository();
68 |
69 | /**
70 | * Get the external repository
71 | *
72 | * @return \Composer\Repository\RepositoryInterface
73 | */
74 | public function getExternalRepository();
75 |
76 | /**
77 | * Get external root directory
78 | *
79 | * @return string
80 | */
81 | public function getExternalRootDirectory();
82 |
83 | /**
84 | * Composer configuration
85 | *
86 | * @return \Composer\Config
87 | */
88 | public function getExternalComposerConfig();
89 |
90 | /**
91 | * Get the full path to the Composer file to process
92 | *
93 | * @return \Composer\Config
94 | */
95 | public function getExternalComposerFilename();
96 |
97 | /**
98 | * Get the internal repository
99 | *
100 | * @return \Composer\Repository\RepositoryInterface
101 | */
102 | public function getInternalRepository();
103 |
104 | /**
105 | * Has an internal repository?
106 | *
107 | * @return bool
108 | */
109 | public function hasInternalRepository();
110 | }
111 |
--------------------------------------------------------------------------------
/EmbeddedComposer.php:
--------------------------------------------------------------------------------
1 |
26 | */
27 | class EmbeddedComposer implements EmbeddedComposerInterface
28 | {
29 | private $classLoader;
30 | private $externalRootDirectory;
31 | private $internalVendorDirectory;
32 | private $hasInternalRepository = false;
33 |
34 | private $repository;
35 |
36 | private $externalRepository;
37 | private $externalComposerConfig;
38 | private $externalComposerFilename;
39 | private $externalVendorDirectory;
40 | private $externalVendorDirectoryOverride = false;
41 |
42 | private $internalRepository;
43 |
44 | /**
45 | * Constructor.
46 | *
47 | * @param ClassLoader $classLoader
48 | * @param string $externalRootDirectory
49 | * @param RepositoryInterface $externalRepository,
50 | * @param string $externalComposerFilename,
51 | * @param Config $externalComposerConfig,
52 | * @param string $externalVendorDirectory,
53 | * @param bool $externalVendorDirectoryOverride,
54 | * @param RepositoryInterface $internalRepository,
55 | * @param string $internalVendorDirectory,
56 | * @param bool $hasInternalRepository,
57 | * @param RepositoryInterface $repository
58 | */
59 | public function __construct(
60 | ClassLoader $classLoader,
61 | $externalRootDirectory,
62 | RepositoryInterface $externalRepository,
63 | $externalComposerFilename,
64 | Config $externalComposerConfig,
65 | $externalVendorDirectory,
66 | $externalVendorDirectoryOverride,
67 | RepositoryInterface $internalRepository,
68 | $internalVendorDirectory,
69 | $hasInternalRepository,
70 | RepositoryInterface $repository
71 | ) {
72 | $this->classLoader = $classLoader;
73 | $this->externalRootDirectory = $externalRootDirectory;
74 | $this->externalRepository = $externalRepository;
75 | $this->externalComposerFilename = $externalComposerFilename;
76 | $this->externalComposerConfig = $externalComposerConfig;
77 | $this->externalVendorDirectory = $externalVendorDirectory;
78 | $this->externalVendorDirectoryOverride = $externalVendorDirectoryOverride;
79 | $this->internalRepository = $internalRepository;
80 | $this->internalVendorDirectory = $internalVendorDirectory;
81 | $this->hasInternalRepository = $hasInternalRepository;
82 | $this->repository = $repository;
83 | }
84 |
85 | /**
86 | * {@inheritdoc}
87 | */
88 | public function getClassLoader()
89 | {
90 | return $this->classLoader;
91 | }
92 |
93 | /**
94 | * {@inheritdoc}
95 | */
96 | public function findPackage($name)
97 | {
98 | $package = null;
99 |
100 | $foundPackages = $this->repository->findPackages($name);
101 | foreach ($foundPackages as $foundPackage) {
102 | if (null === $package || $foundPackage instanceof AliasPackage) {
103 | $package = $foundPackage;
104 | }
105 | }
106 |
107 | return $package;
108 | }
109 |
110 | /**
111 | * {@inheritdoc}
112 | */
113 | public function processAdditionalAutoloads()
114 | {
115 | if ($this->hasInternalRepository) {
116 | $externalAutoload = $this->externalVendorDirectory.'/autoload.php';
117 | if (is_readable($externalAutoload)) {
118 | $this->classLoader->unregister();
119 | include $externalAutoload;
120 | $this->classLoader->register(true);
121 | }
122 | }
123 | }
124 |
125 | /**
126 | * {@inheritdoc}
127 | */
128 | public function createComposer(IOInterface $io)
129 | {
130 | if (! $this->externalVendorDirectoryOverride) {
131 | $originalComposerVendorDir = getenv('COMPOSER_VENDOR_DIR');
132 | putenv('COMPOSER_VENDOR_DIR='.$this->externalVendorDirectory);
133 | }
134 |
135 | $composer = Factory::create($io, $this->externalComposerFilename);
136 |
137 | if (! $this->externalVendorDirectoryOverride) {
138 | if (false !== $originalComposerVendorDir) {
139 | putenv('COMPOSER_VENDOR_DIR='.$originalComposerVendorDir);
140 | }
141 | }
142 |
143 | return $composer;
144 | }
145 |
146 | /**
147 | * {@inheritdoc}
148 | */
149 | public function createInstaller(IOInterface $io)
150 | {
151 | $composer = $this->createComposer($io);
152 | $installer = Installer::create($io, $composer);
153 |
154 | if ($this->hasInternalRepository) {
155 | $installer->setAdditionalInstalledRepository(
156 | $this->internalRepository
157 | );
158 |
159 | $composer->getPluginManager()->loadRepository(
160 | $this->internalRepository
161 | );
162 | }
163 |
164 | return $installer;
165 | }
166 |
167 | /**
168 | * {@inheritdoc}
169 | */
170 | public function getRepository()
171 | {
172 | return $this->repository;
173 | }
174 |
175 | /**
176 | * {@inheritdoc}
177 | */
178 | public function getExternalRepository()
179 | {
180 | return $this->externalRepository;
181 | }
182 |
183 | /**
184 | * {@inheritdoc}
185 | */
186 | public function getExternalRootDirectory()
187 | {
188 | return $this->externalRootDirectory;
189 | }
190 |
191 | /**
192 | * {@inheritdoc}
193 | */
194 | public function getExternalComposerConfig()
195 | {
196 | return $this->externalComposerConfig;
197 | }
198 |
199 | /**
200 | * {@inheritdoc}
201 | */
202 | public function getExternalComposerFilename()
203 | {
204 | return $this->externalComposerFilename;
205 | }
206 |
207 | /**
208 | * {@inheritdoc}
209 | */
210 | public function getInternalRepository()
211 | {
212 | return $this->internalRepository;
213 | }
214 |
215 | /**
216 | * {@inheritdoc}
217 | */
218 | public function hasInternalRepository()
219 | {
220 | return $this->hasInternalRepository;
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/EmbeddedComposerBuilder.php:
--------------------------------------------------------------------------------
1 |
26 | */
27 | class EmbeddedComposerBuilder
28 | {
29 | private $classLoader;
30 | private $externalRootDirectory;
31 | private $internalVendorDirectory;
32 | private $hasInternalRepository = false;
33 |
34 | private $composerFilename;
35 | private $vendorDirectory;
36 | private $error = null;
37 |
38 | /**
39 | * Constructor.
40 | *
41 | * @param ClassLoader $classLoader Class loader
42 | * @param string $externalRootDirectory External root directory
43 | */
44 | public function __construct(ClassLoader $classLoader, $externalRootDirectory = null)
45 | {
46 | $this->classLoader = $classLoader;
47 | $this->externalRootDirectory = $externalRootDirectory ?: getcwd();
48 |
49 | $obj = new \ReflectionClass($classLoader);
50 | $this->internalVendorDirectory = dirname(dirname($obj->getFileName()));
51 |
52 | if (0 === strpos($this->internalVendorDirectory, 'phar://') ||
53 | false === strpos($this->internalVendorDirectory, $this->externalRootDirectory)) {
54 | // If our vendor root does not contain our project root then we
55 | // can assume that we have an internal repository.
56 | $this->hasInternalRepository = true;
57 | }
58 | }
59 |
60 | /**
61 | * Set the name of the composer file
62 | *
63 | * Will default to \Composer\Factory::getComposerFile() if not
64 | * specified.
65 | *
66 | * @param string $composerFilename Composer filename
67 | *
68 | * @return EmbeddedComposerBuilder
69 | */
70 | public function setComposerFilename($composerFilename)
71 | {
72 | $this->composerFilename = $composerFilename;
73 |
74 | return $this;
75 | }
76 |
77 | /**
78 | * Set the vendor directory
79 | *
80 | * Will default to \Composer\Config::get('vendor-dir') if not
81 | * specified.
82 | *
83 | * @param string $vendorDirectory Vendor directory
84 | *
85 | * @return EmbeddedComposerBuilder
86 | */
87 | public function setVendorDirectory($vendorDirectory)
88 | {
89 | $this->vendorDirectory = $vendorDirectory;
90 |
91 | return $this;
92 | }
93 |
94 | /**
95 | * Build
96 | *
97 | * @return EmbeddedComposerInterface
98 | */
99 | public function build()
100 | {
101 | $externalVendorDirectoryOverride = false;
102 |
103 | //
104 | // External Composer Filename
105 | //
106 |
107 | if ($this->hasInternalRepository) {
108 | $externalComposerFilename = $this->composerFilename ?: Factory::getComposerFile();
109 | } else {
110 | $externalComposerFilename = Factory::getComposerFile();
111 | }
112 |
113 | $pristineExternalComposerFilename = $externalComposerFilename;
114 |
115 | if (0 !== strpos($externalComposerFilename, '/')) {
116 | $externalComposerFilename = $this->externalRootDirectory.'/'.$externalComposerFilename;
117 | }
118 |
119 |
120 | //
121 | // External Composer Config
122 | //
123 |
124 | $externalComposerConfig = Factory::createConfig();
125 |
126 | $configJsonFile = new JsonFile($externalComposerFilename);
127 |
128 | if ($configJsonFile->exists()) {
129 | try {
130 | $configJsonFile->validateSchema(JsonFile::LAX_SCHEMA);
131 | $localConfig = $configJsonFile->read();
132 | if (isset($localConfig['config']['vendor-dir'])) {
133 | $externalVendorDirectoryOverride = true;
134 | }
135 | $externalComposerConfig->merge($localConfig);
136 | } catch (ParsingException $e) {
137 | $this->error = $e;
138 | }
139 | } else {
140 | if ($pristineExternalComposerFilename === 'composer.json') {
141 | $message = 'Composer could not find a composer.json file in '.realpath($this->externalRootDirectory);
142 | } else {
143 | $message = 'Composer could not find the config file: '.$externalComposerFilename;
144 | }
145 | $instructions = 'To initialize a project, please create a '.
146 | $pristineExternalComposerFilename.
147 | ' file as described in the http://getcomposer.org/ "Getting Started" section';
148 |
149 | $this->error = new \InvalidArgumentException($message.PHP_EOL.$instructions);
150 | }
151 |
152 | //
153 | // External Vendor Directory
154 | //
155 |
156 | if ($this->hasInternalRepository) {
157 | $externalVendorDirectory = ($externalVendorDirectoryOverride || ! $this->vendorDirectory)
158 | ? $externalComposerConfig->get('vendor-dir')
159 | : $this->vendorDirectory;
160 | } else {
161 | $externalVendorDirectory = $externalComposerConfig->get('vendor-dir');
162 | }
163 |
164 | if (0 !== strpos($externalVendorDirectory, '/')) {
165 | $externalVendorDirectory = $this->externalRootDirectory.'/'.$externalVendorDirectory;
166 | }
167 |
168 |
169 | //
170 | // External Repository
171 | //
172 |
173 | $externalRepository = new InstalledFilesystemRepository(
174 | new JsonFile($externalVendorDirectory.'/composer/installed.json')
175 | );
176 |
177 |
178 | //
179 | // Internal Repository
180 | //
181 |
182 | $internalRepository = new CompositeRepository(array());
183 |
184 | if ($this->hasInternalRepository) {
185 | $internalInstalledRepository = new InstalledFilesystemRepository(
186 | new JsonFile(
187 | $this->internalVendorDirectory.'/composer/installed.json'
188 | )
189 | );
190 |
191 | $internalRepository->addRepository($internalInstalledRepository);
192 | }
193 |
194 | $rootPackageFilename = $this->internalVendorDirectory.'/dflydev/embedded-composer/.root_package.json';
195 | if (file_exists($rootPackageFilename)) {
196 | $rootPackageRepository = new InstalledFilesystemRepository(
197 | new JsonFile($rootPackageFilename)
198 | );
199 |
200 | $internalRepository->addRepository($rootPackageRepository);
201 | }
202 |
203 |
204 | //
205 | // Repository
206 | //
207 |
208 | $repository = new CompositeRepository(array(
209 | $externalRepository,
210 | $internalRepository
211 | ));
212 |
213 |
214 | return new EmbeddedComposer(
215 | $this->classLoader,
216 | $this->externalRootDirectory,
217 | $externalRepository,
218 | $externalComposerFilename,
219 | $externalComposerConfig,
220 | $externalVendorDirectory,
221 | $externalVendorDirectoryOverride,
222 | $internalRepository,
223 | $this->internalVendorDirectory,
224 | $this->hasInternalRepository,
225 | $repository
226 | );
227 | }
228 | }
229 |
--------------------------------------------------------------------------------