Skip to content

Commit 177cb2e

Browse files
Allow customize alias title field (#106)
* allow customize alias source field [ci skip] * fix phpstan report, update rector config [ci skip] * update tests and fix workflow * allow contao 5 again * test fixes * fix test * another fix * phpstan fixes * revert doctrine 4 support * add test for custom title field * raise code coverage --------- Co-authored-by: Thomas Körner <t.koerner@heimrich-hannot.de>
1 parent 3c8c26b commit 177cb2e

10 files changed

Lines changed: 212 additions & 77 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ jobs:
1414
exclude:
1515
- php: 8.1
1616
contao: 5.6.*
17+
- php: 8.4
18+
contao: 4.13.*
1719

1820

1921
steps:

composer.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,27 @@
88
"ext-simplexml": "*",
99
"php": "^8.1",
1010
"contao/core-bundle": "^4.13 || ^5.0",
11-
"doctrine/dbal": "^2.13 || ^3.0",
11+
"doctrine/dbal": "^3.0",
1212
"psr/log": "^1.0 || ^2.0 || ^3.0",
13-
"symfony/config": "^5.4 || ^6.0",
13+
"symfony/config": "^5.4 || ^6.0 || ^7.0",
1414
"symfony/event-dispatcher-contracts": "^1.0 || ^2.0 || ^3.0",
15-
"symfony/filesystem": "^5.4 || ^6.0",
16-
"symfony/http-foundation": "^5.4 || ^6.0",
17-
"symfony/http-kernel": "^5.4 || ^6.0",
18-
"symfony/string": "^5.2 || ^6.0",
15+
"symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
16+
"symfony/http-foundation": "^5.4 || ^6.0 || ^7.0",
17+
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
18+
"symfony/string": "^5.2 || ^6.0 || ^7.0",
1919
"twig/twig": "^3.0"
2020
},
2121
"require-dev": {
2222
"contao/manager-plugin": "^2.0",
23+
"contao/news-bundle": "^4.13 || ^5.0",
2324
"contao/test-case": "^4.13 || ^5.0",
2425
"heimrichhannot/contao-test-utilities-bundle": "^0.1",
2526
"phpunit/phpunit": "^9.0 || ^10.0 || ^11.0",
2627
"php-coveralls/php-coveralls": "^2.0",
2728
"symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0",
2829
"phpstan/phpstan": "^1.10 || ^2.0",
2930
"phpstan/phpstan-symfony": "^1.2 || ^2.0",
30-
"rector/rector": "^1.2 || ^2.0",
31+
"rector/rector": "^1.2 || ^2.3.3",
3132
"contao/contao-rector": "dev-main"
3233
},
3334
"autoload": {

rector.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,45 @@
55
use Contao\Rector\Set\ContaoLevelSetList;
66
use Contao\Rector\Set\ContaoSetList;
77
use Rector\Config\RectorConfig;
8+
use Rector\Php81\Rector\Array_\ArrayToFirstClassCallableRector;
89
use Rector\Php84\Rector\Param\ExplicitNullableParamTypeRector;
910
use Rector\Set\ValueObject\LevelSetList;
1011
use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
12+
use Rector\ValueObject\PhpVersion;
1113

1214
return RectorConfig::configure()
1315
->withPaths([
1416
__DIR__ . '/src',
1517
])
16-
->withPhpVersion(\Rector\ValueObject\PhpVersion::PHP_84)
18+
->withPhpVersion(PhpVersion::PHP_84)
1719
->withRules([
1820
AddVoidReturnTypeWhereNoReturnRector::class,
1921
# In Vorbereitung für PHP 8.4:
2022
ExplicitNullableParamTypeRector::class
2123
])
2224

23-
->withImportNames(importShortClasses: false, removeUnusedImports: true)
24-
->withComposerBased(symfony: true)
25+
->withImportNames(
26+
importShortClasses: false,
27+
removeUnusedImports: true,
28+
)
29+
->withComposerBased(
30+
twig: true,
31+
doctrine: true,
32+
phpunit: true,
33+
symfony: true,
34+
)
2535
->withSets([
2636
LevelSetList::UP_TO_PHP_81,
2737
# Erst mit Symfony 6 (Contao 5) nutzen:
2838
// SymfonySetList::ANNOTATIONS_TO_ATTRIBUTES,
2939
ContaoLevelSetList::UP_TO_CONTAO_413,
3040
ContaoSetList::FQCN,
3141
ContaoSetList::ANNOTATIONS_TO_ATTRIBUTES,
32-
]);
42+
])
43+
->withSkip([
44+
ArrayToFirstClassCallableRector::class,
45+
])
46+
47+
48+
49+
;

src/Dca/AliasFieldConfiguration.php

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,46 @@
66

77
class AliasFieldConfiguration extends DcaFieldConfiguration
88
{
9+
/**
10+
* @internal
11+
* @deprecated
12+
*/
913
public ?array $aliasExistCallback = [AliasDcaFieldListener::class, 'onFieldsAliasSaveCallback'];
1014

15+
/**
16+
* @internal
17+
*/
1118
public string $fieldName = 'alias';
1219

1320
/**
14-
* Override the default alias exist function. Provide as [Class, 'method'].
15-
*
21+
* @internal
22+
*/
23+
public string $titleField = 'title';
24+
25+
/**
26+
* @internal
27+
*/
28+
public ?array $generateAliasCallback = [AliasDcaFieldListener::class, 'onFieldsAliasSaveCallback'];
29+
30+
/**
1631
* @param array<string, string> $aliasExistCallback
32+
* @deprecated Deprecated since version 3.10. Use setGenerateAliasCallback instead.
33+
* @codeCoverageIgnore
1734
*/
1835
public function setAliasExistCallback(?array $aliasExistCallback): AliasFieldConfiguration
1936
{
20-
$this->aliasExistCallback = $aliasExistCallback;
37+
$this->generateAliasCallback = $aliasExistCallback;
38+
return $this;
39+
}
40+
41+
/**
42+
* Override the default alias generation function. Provide as [Class, 'method'].
43+
*
44+
* @param array<string, string> $callback
45+
*/
46+
public function setGenerateAliasCallback(?array $callback): AliasFieldConfiguration
47+
{
48+
$this->generateAliasCallback = $callback;
2149
return $this;
2250
}
2351

@@ -26,4 +54,13 @@ public function setFieldName(string $fieldName): AliasFieldConfiguration
2654
$this->fieldName = $fieldName;
2755
return $this;
2856
}
57+
58+
/**
59+
* Set the field name from which the alias should be generated.
60+
*/
61+
public function setTitleField(string $titleField): AliasFieldConfiguration
62+
{
63+
$this->titleField = $titleField;
64+
return $this;
65+
}
2966
}

src/EntityFinder/EntityFinderHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,4 @@ public function setRow(array $arrData)
201201
}
202202
};
203203
}
204-
}
204+
}

src/EntityFinder/Finder.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ private function news(int $id): ?Element
255255
NewsModel::getTable(),
256256
'News ' . $model->headline . ' (ID: ' . $model->id . ')',
257257
(function () use ($model): \Generator {
258-
/* @phpstan-ignore class.notFound */
259258
yield ['table' => NewsArchiveModel::getTable(), 'id' => $model->pid];
260259
})()
261260
);

src/EventListener/DcaField/AliasDcaFieldListener.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public function onLoadDataContainer(string $table): void
2323
$registration = AliasField::getRegistrations()[$table];
2424

2525
$field = AliasField::getField();
26-
if (is_array($registration->aliasExistCallback)) {
27-
$field['save_callback'][] = $registration->aliasExistCallback;
26+
if (is_array($registration->generateAliasCallback)) {
27+
$field['save_callback'][] = $registration->generateAliasCallback;
2828
}
2929

3030
$this->applyDefaultFieldAdjustments($field, $registration);
@@ -40,16 +40,29 @@ public function onFieldsAliasSaveCallback($value, DataContainer $dc)
4040
->execute($alias, $dc->id)
4141
->numRows > 0);
4242

43+
if (method_exists($dc, 'getCurrentRecord')) {
44+
$row = $dc->getCurrentRecord();
45+
} else {
46+
/**
47+
* Contao 4 fallback
48+
* @todo Remove when contao 5 only
49+
* @phpstan-ignore property.notFound
50+
*/
51+
$row = $dc->activeRecord?->row() ?? [];
52+
}
53+
4354
// Generate an alias if there is none
4455
if (!$value) {
56+
/** @var ?AliasFieldConfiguration $fieldConfiguration */
57+
$fieldConfiguration = AliasField::getRegistrations()[$dc->table] ?? null;
58+
$titleField = $fieldConfiguration?->titleField ?? 'title';
59+
4560
$value = $this->container->get('contao.slug')->generate(
46-
/** @phpstan-ignore property.notFound */
47-
(string)$dc->activeRecord->title,
48-
/** @phpstan-ignore property.notFound */
49-
(int)$dc->activeRecord->pid,
61+
(string)$row[$titleField] ?? '',
62+
(int)$row['pid'],
5063
$aliasExists
5164
);
52-
} elseif (preg_match('/^[1-9]\d*$/', (string) $value)) {
65+
} elseif (preg_match('/^[1-9]\d*$/', (string)$value)) {
5366
throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['aliasNumeric'], $value));
5467
} elseif ($aliasExists($value)) {
5568
throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['aliasExists'], $value));

src/Util/UserUtil.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
use Contao\Model\Collection;
1717
use Contao\StringUtil;
1818
use Contao\UserModel;
19-
use HeimrichHannot\UtilsBundle\Util\DatabaseUtil;
20-
use HeimrichHannot\UtilsBundle\Util\ModelUtil;
2119
use HeimrichHannot\UtilsBundle\Util\UserUtil\UserType;
2220

2321
class UserUtil

0 commit comments

Comments
 (0)