浏览代码

Merge pull request #8224 from cvo-technologies/plugin-split-name

Add method to convert namespaced class names to plugin split names
José Lorenzo Rodríguez 10 年之前
父节点
当前提交
a524970e89
共有 2 个文件被更改,包括 151 次插入0 次删除
  1. 85 0
      src/Core/App.php
  2. 66 0
      tests/TestCase/Core/AppTest.php

+ 85 - 0
src/Core/App.php

@@ -74,6 +74,91 @@ class App
     }
 
     /**
+     * Returns the plugin split name of a class
+     *
+     * Examples:
+     *
+     * ```
+     * App::shortName(
+     *     'SomeVendor\SomePlugin\Controller\Component\TestComponent',
+     *     'Controller/Component',
+     *     'Component'
+     * )
+     * ```
+     *
+     * Returns: SomeVendor/SomePlugin.Test
+     *
+     * ```
+     * App::shortName(
+     *     'SomeVendor\SomePlugin\Controller\Component\Subfolder\TestComponent',
+     *     'Controller/Component',
+     *     'Component'
+     * )
+     * ```
+     *
+     * Returns: SomeVendor/SomePlugin.Subfolder/Test
+     *
+     * ```
+     * App::shortName(
+     *     'Cake\Controller\Component\AuthComponent',
+     *     'Controller/Component',
+     *     'Component'
+     * )
+     * ```
+     *
+     * Returns: Auth
+     *
+     * @param string $class Class name
+     * @param string $type Type of class
+     * @param string $suffix Class name suffix
+     * @return string Plugin split name of class
+     */
+    public static function shortName($class, $type = '', $suffix = '')
+    {
+        // Split class in namespace parts
+        $namespaceParts = explode('\\', $class);
+        $typeParts = explode('/', $type);
+        $typeOffset = null;
+        $namespacePartCount = count($namespaceParts);
+        $typePartCount = count($typeParts);
+
+        // Determine offset of the type
+        for ($index = 0; $index < $namespacePartCount; $index++) {
+            // Continue if the current slice is not of the type
+            if (array_slice($namespaceParts, $index, $typePartCount) !== $typeParts) {
+                continue;
+            }
+
+            $typeOffset = $index;
+        }
+
+        // Get plugin namespace from the namespace part before the type
+        $pluginNamespace = implode('\\', array_slice($namespaceParts, 0, $typeOffset));
+
+        // Get name from the namespace part after the type
+        $name = implode('/', array_slice($namespaceParts, $typeOffset + $typePartCount));
+        // Remove the suffix if it has been set
+        if ($suffix) {
+            $name = substr($name, 0, 0 - strlen($suffix));
+        }
+
+        // Ignore CakePHP and app namespaces
+        $ignoredNamespaces = [
+            'Cake',
+            Configure::read('App.namespace')
+        ];
+        if (in_array($pluginNamespace, $ignoredNamespaces)) {
+            $pluginNamespace = '';
+        }
+
+        // Convert plugin namespace to plugin name
+        $pluginName = implode('/', explode('\\', $pluginNamespace));
+
+        // Return plugin split formatted name with plugin name and class name
+        return implode('.', array_filter(pluginSplit($name, true, $pluginName)));
+    }
+
+    /**
      * _classExistsInBase
      *
      * Test isolation wrapper

+ 66 - 0
tests/TestCase/Core/AppTest.php

@@ -69,6 +69,24 @@ class AppTest extends TestCase
     }
 
     /**
+     * testShortName
+     *
+     * @param string $class Class name
+     * @param string $type Class type
+     * @param string $suffix Class suffix
+     * @param mixed $expected Expected value.
+     * @return void
+     * @dataProvider shortNameProvider
+     */
+    public function testShortName($class, $type, $suffix = '', $expected = false)
+    {
+        Configure::write('App.namespace', 'TestApp');
+
+        $return = TestApp::shortName($class, $type, $suffix);
+        $this->assertSame($expected, $return);
+    }
+
+    /**
      * classnameProvider
      *
      * Return test permutations for testClassname method. Format:
@@ -125,6 +143,54 @@ class AppTest extends TestCase
     }
 
     /**
+     * pluginSplitNameProvider
+     *
+     * Return test permutations for testClassname method. Format:
+     *  classname
+     *  type
+     *  suffix
+     *  expected return value
+     *
+     * @return void
+     */
+    public function shortNameProvider()
+    {
+        return [
+            ['TestApp\In\ExistsApp', 'In', 'App', 'Exists'],
+            ['TestApp\In\Also\ExistsApp', 'In', 'App', 'Also/Exists'],
+            ['TestApp\Exists\In\AlsoApp', 'Exists/In', 'App', 'Also'],
+            ['TestApp\Exists\In\Subfolder\AlsoApp', 'Exists/In/Subfolder', 'App', 'Also'],
+            ['TestApp\Suffix\No', 'Suffix', '', 'No'],
+
+            ['MyPlugin\In\ExistsSuffix', 'In', 'Suffix', 'MyPlugin.Exists'],
+            ['MyPlugin\In\Also\ExistsSuffix', 'In', 'Suffix', 'MyPlugin.Also/Exists'],
+            ['MyPlugin\Exists\In\AlsoSuffix', 'Exists/In', 'Suffix', 'MyPlugin.Also'],
+            ['MyPlugin\Exists\In\Subfolder\AlsoSuffix', 'Exists/In/Subfolder', 'Suffix', 'MyPlugin.Also'],
+            ['MyPlugin\Suffix\No', 'Suffix', '', 'MyPlugin.No'],
+
+            ['Vend\MPlugin\In\ExistsSuffix', 'In', 'Suffix', 'Vend/MPlugin.Exists'],
+            ['Vend\MPlugin\In\Also\ExistsSuffix', 'In', 'Suffix', 'Vend/MPlugin.Also/Exists'],
+            ['Vend\MPlugin\Exists\In\AlsoSuffix', 'Exists/In', 'Suffix', 'Vend/MPlugin.Also'],
+            ['Vend\MPlugin\Exists\In\Subfolder\AlsoSuffix', 'Exists/In/Subfolder', 'Suffix', 'Vend/MPlugin.Also'],
+            ['Vend\MPlugin\Suffix\No', 'Suffix', '', 'Vend/MPlugin.No'],
+
+            ['Cake\In\ExistsCake', 'In', 'Cake', 'Exists'],
+            ['Cake\In\Also\ExistsCake', 'In', 'Cake', 'Also/Exists'],
+            ['Cake\Exists\In\AlsoCake', 'Exists/In', 'Cake', 'Also'],
+            ['Cake\Exists\In\Subfolder\AlsoCake', 'Exists/In/Subfolder', 'Cake', 'Also'],
+            ['Cake\Suffix\No', 'Suffix', '', 'No'],
+
+            // Real examples returning classnames
+            ['Cake\Core\App', 'Core', '', 'App'],
+            ['Cake\Controller\Component\AuthComponent', 'Controller/Component', 'Component', 'Auth'],
+            ['Cake\Cache\Engine\FileEngine', 'Cache/Engine', 'Engine', 'File'],
+            ['Cake\Shell\Task\CommandTask', 'Shell/Task', 'Task', 'Command'],
+            ['Cake\Shell\Task\Upgrade\LocationsTask', 'Shell/Task', 'Task', 'Upgrade/Locations'],
+            ['TestApp\Controller\PagesController', 'Controller', 'Controller', 'Pages'],
+        ];
+    }
+
+    /**
      * test path() with a plugin.
      *
      * @return void