[TASK] Turn todos into @todo to find them easier
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Package / PackageFactory.php
1 <?php
2 namespace TYPO3\CMS\Core\Package;
3
4 /* *
5 * This script belongs to the TYPO3 Flow framework. *
6 * *
7 * It is free software; you can redistribute it and/or modify it under *
8 * the terms of the GNU Lesser General Public License, either version 3 *
9 * of the License, or (at your option) any later version. *
10 * *
11 * The TYPO3 project - inspiring people to share! *
12 * */
13
14 use TYPO3\Flow\Utility\Files;
15
16 /**
17 * Class for building Packages
18 * Adapted from FLOW for TYPO3 CMS
19 */
20 class PackageFactory extends \TYPO3\Flow\Package\PackageFactory {
21
22 /**
23 * @var PackageManager
24 */
25 protected $packageManager;
26
27 /**
28 * Constructor
29 *
30 * @param \TYPO3\Flow\Package\PackageManager $packageManager
31 */
32 public function __construct(PackageManager $packageManager) {
33 $this->packageManager = $packageManager;
34 }
35
36 /**
37 * Returns a package instance.
38 *
39 * @param string $packagesBasePath the base install path of packages,
40 * @param string $packagePath path to package, relative to base path
41 * @param string $packageKey key / name of the package
42 * @param string $classesPath path to the classes directory, relative to the package path
43 * @param string $manifestPath path to the package's Composer manifest, relative to package path, defaults to same path
44 * @return \TYPO3\Flow\Package\PackageInterface
45 * @throws \TYPO3\Flow\Package\Exception\CorruptPackageException
46 */
47 public function create($packagesBasePath, $packagePath, $packageKey, $classesPath, $manifestPath = '') {
48 $packagePath = Files::getNormalizedPath(Files::concatenatePaths(array($packagesBasePath, $packagePath)));
49 $packageClassPathAndFilename = Files::concatenatePaths(array($packagePath, 'Classes/' . str_replace('.', '/', $packageKey) . '/Package.php'));
50 $alternativeClassPathAndFilename = Files::concatenatePaths(array($packagePath, 'Classes/Package.php'));
51 $packageClassPathAndFilename = @file_exists($alternativeClassPathAndFilename) ? $alternativeClassPathAndFilename : $packageClassPathAndFilename;
52 if (@file_exists($packageClassPathAndFilename)) {
53 require_once($packageClassPathAndFilename);
54 if (substr($packagePath, 0, strlen(PATH_typo3)) === PATH_typo3 && strpos($packageKey, '.') === FALSE) {
55 // @todo Remove this exception once the systextension are renamed to proper Flow naming scheme packages
56 $packageClassName = 'TYPO3\\CMS\\' . \TYPO3\CMS\Core\Utility\GeneralUtility::underscoredToUpperCamelCase($packageKey) . '\Package';
57 } else {
58 $packageClassName = str_replace('.', '\\', $packageKey) . '\Package';
59 }
60 if (!class_exists($packageClassName, FALSE)) {
61 throw new \TYPO3\Flow\Package\Exception\CorruptPackageException(sprintf('The package "%s" does not contain a valid package class. Check if the file "%s" really contains a class called "%s".', $packageKey, $packageClassPathAndFilename, $packageClassName), 1327587092);
62 }
63 } else {
64 $emConfPath = Files::concatenatePaths(array($packagePath, 'ext_emconf.php'));
65 $packageClassName = @file_exists($emConfPath) ? \TYPO3\CMS\Core\Package\Package::class : \TYPO3\Flow\Package\Package::class;
66 }
67
68 /** @var $package \TYPO3\Flow\Package\PackageInterface */
69 $package = new $packageClassName($this->packageManager, $packageKey, $packagePath, $classesPath, $manifestPath);
70
71 return $package;
72 }
73
74 /**
75 * Resolves package key from Composer manifest
76 *
77 * If it is a Flow package the name of the containing directory will be used.
78 *
79 * Else if the composer name of the package matches the first part of the lowercased namespace of the package, the mixed
80 * case version of the composer name / namespace will be used, with backslashes replaced by dots.
81 *
82 * Else the composer name will be used with the slash replaced by a dot
83 *
84 * @param object $manifest
85 * @param string $packagePath
86 * @param string $packagesBasePath
87 * @throws \TYPO3\Flow\Package\Exception\InvalidPackageManifestException
88 * @return string
89 */
90 public static function getPackageKeyFromManifest($manifest, $packagePath, $packagesBasePath) {
91 if (!is_object($manifest)) {
92 throw new \TYPO3\Flow\Package\Exception\InvalidPackageManifestException('Invalid composer manifest in package path: ' . $packagePath, 1348146451);
93 }
94 if (isset($manifest->type) && substr($manifest->type, 0, 10) === 'typo3-cms-') {
95 $relativePackagePath = substr($packagePath, strlen($packagesBasePath));
96 $packageKey = substr($relativePackagePath, strpos($relativePackagePath, '/') + 1, -1);
97 /**
98 * @todo check that manifest name and directory follows convention
99 */
100 $packageKey = preg_replace('/[^A-Za-z0-9._-]/', '', $packageKey);
101 return $packageKey;
102 } else {
103 return parent::getPackageKeyFromManifest($manifest, $packagePath, $packagesBasePath);
104 }
105 }
106
107 }