[FEATURE] Add possibility for extensions to register class maps 23/43523/7
authorHelmut Hummel <helmut.hummel@typo3.org>
Thu, 24 Sep 2015 13:57:57 +0000 (15:57 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sat, 26 Sep 2015 17:46:57 +0000 (19:46 +0200)
With the old class loader it was possible for extension authors
to register several classes in an ext_autoload.php file.

This possibility was completely removed with introduction of composer class loading.
In composer mode, one can fully benefit from composer and its class loading options.
However TYPO3 installations in non composer mode (extracted and symlinked
archive of sources), lack this functionality completely.

It could however be useful to have that for some edge cases or legacy code,
without completely relying on a full scan for classes in the complete extension
directory (when no new class loading info is found at all), which can be an issue
of its own.

With this change it is also possible to define a "classmap" section
in the composer.json or ext_emcomf.php file.

Resolves: #70078
Releases: master
Change-Id: I86f65fbb479eb46160ecef3a547a91e453ee5764
Reviewed-on: http://review.typo3.org/43523
Reviewed-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Nicole Cordes <typo3@cordes.co>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/core/Classes/Core/ClassLoadingInformationGenerator.php
typo3/sysext/core/Documentation/Changelog/master/Feature-68700-AutoloadDefinitionCanBeProvidedInExt_emconfphp.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-70078-ExtensionsCanProvideAClassMapForClassLoading.rst [new file with mode: 0644]

index 1ce3c3b..6920091 100644 (file)
@@ -44,26 +44,34 @@ class ClassLoadingInformationGenerator {
                $psr4 = array();
                $packagePath = $package->getPackagePath();
 
-               $manifest = $this->getPackageManager()->getComposerManifest($package->getPackagePath());
-               if (!empty($manifest->autoload->{'psr-4'})) {
-                       $psr4manifest = json_decode(json_encode($manifest->autoload->{'psr-4'}), TRUE);
-                       if (is_array($psr4manifest)) {
-                               foreach ($psr4manifest as $namespacePrefix => $path) {
+               $manifest = $this->getPackageManager()->getComposerManifest($packagePath);
+
+               if (empty($manifest->autoload)) {
+                       // Legacy mode: Scan the complete extension directory for class files
+                       $classMap = $this->createClassMap($packagePath, $useRelativePaths, TRUE);
+               } else {
+                       $autoloadDefinition = json_decode(json_encode($manifest->autoload), TRUE);
+                       if (!empty($autoloadDefinition['psr-4']) && is_array($autoloadDefinition['psr-4'])) {
+                               $classLoaderPrefixesPsr4 = $this->getClassLoader()->getPrefixesPsr4();
+                               foreach ($autoloadDefinition['psr-4'] as $namespacePrefix => $path) {
                                        $namespacePath = $packagePath . $path;
                                        if ($useRelativePaths) {
                                                $psr4[$namespacePrefix] = $this->makePathRelative($namespacePath, realpath($namespacePath));
                                        } else {
                                                $psr4[$namespacePrefix] = $namespacePath;
                                        }
-                                       if (!empty($this->getClassLoader()->getPrefixesPsr4()[$namespacePrefix])) {
+                                       if (!empty($classLoaderPrefixesPsr4[$namespacePrefix])) {
                                                // The namespace prefix has been registered already, which means there also might be
                                                // a class map which we need to override
                                                $classMap = array_merge($classMap, $this->createClassMap($namespacePath, $useRelativePaths, FALSE, $namespacePrefix));
                                        }
                                }
                        }
-               } else {
-                       $classMap = $this->createClassMap($packagePath, $useRelativePaths, TRUE);
+                       if (!empty($autoloadDefinition['classmap']) && is_array($autoloadDefinition['classmap'])) {
+                               foreach ($autoloadDefinition['classmap'] as $path) {
+                                       $classMap = array_merge($classMap, $this->createClassMap($packagePath . $path, $useRelativePaths));
+                               }
+                       }
                }
 
                return array('classMap' => $classMap, 'psr-4' => $psr4);
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-68700-AutoloadDefinitionCanBeProvidedInExt_emconfphp.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-68700-AutoloadDefinitionCanBeProvidedInExt_emconfphp.rst
new file mode 100644 (file)
index 0000000..6b7fc20
--- /dev/null
@@ -0,0 +1,70 @@
+=======================================================================
+Feature: #68700 - Autoload definition can be provided in ext_emconf.php
+=======================================================================
+
+Description
+===========
+
+It is now possible for extensions to provide one or more PSR-4 definitions,
+in the ext_emconf.php file.
+
+While it was possible to define a psr-4 section in a composer.json before already, now it is also
+possible to define an autoload/psr-4 section in the ext_emconf.php file as well, so that extension authors
+do not need to provide a composer.json just for that any more.
+
+This is the new recommended way to register classes for TYPO3.
+
+Example ext_emconf.php:
+
+.. code-block:: php
+
+       <?php
+       $EM_CONF[$_EXTKEY] = array (
+         'title' => 'Extension skeleton for TYPO3 7',
+         'description' => 'Description for ext',
+         'category' => 'Example Extensions',
+         'author' => 'Helmut Hummel',
+         'author_email' => 'info@helhum.io',
+         'author_company' => 'helhum.io',
+         'shy' => '',
+         'priority' => '',
+         'module' => '',
+         'state' => 'stable',
+         'internal' => '',
+         'uploadfolder' => '0',
+         'createDirs' => '',
+         'modify_tables' => '',
+         'clearCacheOnLoad' => 0,
+         'lockType' => '',
+         'version' => '0.0.1',
+         'constraints' =>
+         array (
+               'depends' =>
+               array (
+                 'typo3' => '7.5.0-7.99.99',
+               ),
+               'conflicts' =>
+               array (
+               ),
+               'suggests' =>
+               array (
+               ),
+         ),
+         'autoload' =>
+         array(
+               'psr-4' =>
+               array(
+                 'Helhum\\ExtScaffold\\' => 'Classes'
+               )
+         )
+       );
+
+
+Impact
+======
+
+Without providing an autoload section, TYPO3 scans the complete extension directory for PHP class files and registers them all.
+This includes test classes or classes of third party libraries, which might lead to unexpected results.
+
+Therefore it is recommended to provide such an autoload section in an extension. It will be ignored in older TYPO3 versions, so
+there will be no issue with backwards compatibility.
\ No newline at end of file
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-70078-ExtensionsCanProvideAClassMapForClassLoading.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-70078-ExtensionsCanProvideAClassMapForClassLoading.rst
new file mode 100644 (file)
index 0000000..dfd0d10
--- /dev/null
@@ -0,0 +1,75 @@
+======================================================================
+Feature: #70078 - Extensions can provide a class map for class loading
+======================================================================
+
+Description
+===========
+
+With the old class loader it was possible for extension authors
+to register several classes in an ext_autoload.php file.
+
+This possibility was completely removed with introduction of composer class loading.
+In composer mode, one can fully benefit from composer and its class loading options.
+However TYPO3 installations in non composer mode (extracted and symlinked
+archive of sources), lack this functionality completely.
+
+Now it is possible to provide a class map section in either the composer.json file
+or the ext_emconf.php file. This section will be evaluated and used also in non composer mode.
+
+Example ext_emconf.php file:
+
+.. code-block:: php
+
+       <?php
+       $EM_CONF[$_EXTKEY] = array (
+         'title' => 'Extension skeleton for TYPO3 7',
+         'description' => 'Description for ext',
+         'category' => 'Example Extensions',
+         'author' => 'Helmut Hummel',
+         'author_email' => 'info@helhum.io',
+         'author_company' => 'helhum.io',
+         'shy' => '',
+         'priority' => '',
+         'module' => '',
+         'state' => 'stable',
+         'internal' => '',
+         'uploadfolder' => '0',
+         'createDirs' => '',
+         'modify_tables' => '',
+         'clearCacheOnLoad' => 0,
+         'lockType' => '',
+         'version' => '0.0.1',
+         'constraints' =>
+         array (
+               'depends' =>
+               array (
+                 'typo3' => '7.5.0-7.99.99',
+               ),
+               'conflicts' =>
+               array (
+               ),
+               'suggests' =>
+               array (
+               ),
+         ),
+         'autoload' =>
+         array(
+               'psr-4' =>
+               array(
+                 'Helhum\\ExtScaffold\\' => 'Classes'
+               ),
+               'classmap' =>
+               array(
+                 'Resources/PHP/Libs'
+               )
+         )
+       );
+
+In the example configuration the path ``Resources/PHP/Libs`` is parsed for PHP files which are automatically added
+to the class loader.
+
+Impact
+======
+
+Extensions that target TYPO3 6.2 LTS and 7 LTS can now provide a class map in ext_emconf.php which is only evaluated in
+TYPO3 7 LTS and an ext_autoload.php which is only evaluated in 6.2 LTS for maximum flexibility and compatibility.
\ No newline at end of file