Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions src/V3/BaseVariable.php
Original file line number Diff line number Diff line change
Expand Up @@ -341,17 +341,33 @@ public function getType()
* @return string This variable's {@link Horde_Form_Type} name.
*
* Override with a simple return 'literal' string in your own types.
*
* @api
*
* The default derives the type name from the class namespace so app
* variables map back to their legacy `{app}_form_type_{name}` handles
* (used e.g. by `Horde_Core_Ui_VarRenderer::render()` when dispatching
* to `_renderVarInput_{typename}` methods). Three shapes are covered:
*
* - `Horde\Form\V3\FooVariable` → `foo`
* Vendor-owned horde/form variables use the bare name.
* - `Horde\{App}\...\FooVariable` → `{app}_form_type_foo`
* Vendor-namespaced app variables (PSR-4 `Horde\Ingo\Form\V3\…`).
* - `{App}\...\FooVariable` → `{app}_form_type_foo`
* Legacy pre-PSR-4 app variables (`Ingo\Form\V3\…`).
*
* @api
*/
public function getTypeName(): string
{
$parts = explode('\\', $this::class);
$app = strtolower($parts[0]);
$name = strtolower(substr($parts[count($parts) - 1], 0, -8));
if ($app !== 'horde') {
// legacy
$name = $app . '_form_type_' . $name;
$name = strtolower(substr($parts[count($parts) - 1], 0, -8));
$vendor = strtolower($parts[0]);
if ($vendor !== 'horde') {
// Legacy pre-PSR-4 app layout: `{App}\...\FooVariable`.
return $vendor . '_form_type_' . $name;
}
if (count($parts) >= 3 && strtolower($parts[1]) !== 'form') {
// Vendor-namespaced app layout: `Horde\{App}\...\FooVariable`.
return strtolower($parts[1]) . '_form_type_' . $name;
}
return $name;
}
Expand Down
4 changes: 4 additions & 0 deletions test/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// Load Composer autoloader
require_once __DIR__ . '/../vendor/autoload.php';

// Fixture classes declared in namespaces that PSR-4 autoloading in test/
// cannot express (see BaseVariable::getTypeName() coverage).
require_once __DIR__ . '/v3/fixtures/GetTypeNameFixtures.php';

// Setup minimal global mocks for Horde dependencies
// These are needed by Horde_Form when form tokens are enabled

Expand Down
18 changes: 18 additions & 0 deletions test/v3/V3BaseVariableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,24 @@ public function testGetTypeName(): void
$this->assertEquals('text', $var->getTypeName());
}

public function testGetTypeNameForVendorNamespacedAppVariable(): void
{
// `Horde\Fakeapp\Form\V3\FoldersVariable` — modern PSR-4 app layout.
// See test/v3/fixtures/GetTypeNameFixtures.php.
$var = new \Horde\Fakeapp\Form\V3\FoldersVariable('Folder', 'folder', false);

$this->assertEquals('fakeapp_form_type_folders', $var->getTypeName());
}

public function testGetTypeNameForLegacyAppVariable(): void
{
// `Fakeapp\Form\V3\FoldersVariable` — pre-PSR-4 legacy app layout.
// See test/v3/fixtures/GetTypeNameFixtures.php.
$var = new \Fakeapp\Form\V3\FoldersVariable('Folder', 'folder', false);

$this->assertEquals('fakeapp_form_type_folders', $var->getTypeName());
}

public function testIsRequired(): void
{
$requiredVar = new TextVariable('Name', 'name', true);
Expand Down
48 changes: 48 additions & 0 deletions test/v3/fixtures/GetTypeNameFixtures.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

/**
* Fixtures for BaseVariable::getTypeName() tests.
*
* Copyright 2026 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (LGPL-2.1).
*
* Declared in dedicated namespace blocks so getTypeName() can be exercised
* against class-name shapes that PSR-4 autoloading in test/ (which is mapped
* to Horde\Form\Test\) cannot express directly.
*
* @category Horde
* @package Form
* @subpackage UnitTests
* @license http://www.horde.org/licenses/lgpl21 LGPL-2.1
*/

namespace Horde\Fakeapp\Form\V3 {

use Horde\Form\V3\BaseVariable;

/**
* Vendor-namespaced app variable shape: `Horde\{App}\...\FooVariable`.
*
* Expected getTypeName(): `fakeapp_form_type_folders`.
*/
class FoldersVariable extends BaseVariable
{
}
}

namespace Fakeapp\Form\V3 {

use Horde\Form\V3\BaseVariable;

/**
* Legacy pre-PSR-4 app variable shape: `{App}\...\FooVariable`.
*
* Expected getTypeName(): `fakeapp_form_type_folders`.
*/
class FoldersVariable extends BaseVariable
{
}
}
Loading