Skip to content

Commit

Permalink
Add method to convert namespaced class names to plugin split names
Browse files Browse the repository at this point in the history
  • Loading branch information
Marlinc committed Feb 10, 2016
1 parent e0c901c commit 5705dc6
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/Core/App.php
Expand Up @@ -73,6 +73,92 @@ public static function className($class, $type = '', $suffix = '')
return false;
}

/**
* 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;
break;
}

// 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
*
Expand Down
66 changes: 66 additions & 0 deletions tests/TestCase/Core/AppTest.php
Expand Up @@ -68,6 +68,24 @@ public function testClassname($class, $type, $suffix = '', $existsInBase = false
$this->assertSame($expected, $return);
}

/**
* 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
*
Expand Down Expand Up @@ -124,6 +142,54 @@ public function classnameProvider()
];
}

/**
* 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.
*
Expand Down

0 comments on commit 5705dc6

Please sign in to comment.