1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
declare(strict_types=1);
namespace Piwik\Plugins\CoreHome\EntityDuplicator;
/**
*
*/
class EntityDuplicatorHelper
{
/**
* Update the provided name with a number suffix. It will either add a suffix or increment the number in the suffix.
* This can be used to simplify ensuring that the name of a copied item is unique. This doesn't handle querying the
* database for duplicates, so that will need to be handled case-by-case.
*
* @param string $name The name that needs to be updated with a number suffix. If no suffix exists, one will be
* added. If one already exists, the number in the suffix will be incremented.
* @param int $maxLength Optional number indicates the maximum allowed length. If adding the suffix exceeds the max,
* the string will be truncated just enough to allow the suffix. Default is -1 allowing infinite length.
* @return string Name with the updated number suffix
* @throws \Exception If the maximum length is too small to accommodate a suffix like " (1)".
*/
public static function incrementNameWithNumericalSuffix(string $name, int $maxLength = -1): string
{
$modifiedName = $name;
// First check if the name already has a number suffix
$matches = [];
$number = 1;
if (preg_match('/ \(\d+\)$/', $name, $matches)) {
// Increment the number in the name suffix
$number = intval(str_replace(['(', ')'], '', $matches[0]));
++$number;
$modifiedName = str_replace($matches[0], '', $name);
}
// Make sure that the maximum length isn't too small and won't result in the suffix replacing the whole name
$newNumberLength = strlen((string) $number);
if ($maxLength !== -1 && $maxLength <= $newNumberLength + 3) {
throw new \Exception('The maximum name length cannot be less than the length of the suffix.');
}
// Make sure that we don't exceed the max length the name fields
if ($maxLength !== -1 && strlen($modifiedName . " ($number)") > $maxLength) {
$modifiedName = substr($modifiedName, 0, ($maxLength - 3) - strlen((string) $number));
}
$modifiedName .= " ($number)";
return $modifiedName;
}
/**
* Takes a list of existing names and updates the provided name with a numerical suffix until it's unique. It also
* truncates the name to make sure that it doesn't exceed the maximum length.
*
* @param string $name The name that needs to be updated with a number suffix. If no suffix exists, one will be
* added. If one already exists, the number in the suffix will be incremented.
* @param string[] $names List of existing names to compare against in order to provide a unique name.
* @param int $maxLength Optional number indicates the maximum allowed length. If adding the suffix exceeds the max,
* the string will be truncated just enough to allow the suffix. Default is -1 allowing infinite length.
* @return string
* @throws \Exception If the maximum length is too small".
*/
public static function getUniqueNameComparedToList(string $name, array $names, int $maxLength = -1)
{
// Make sure that the name is at least one character long
if ($maxLength !== -1 && $maxLength < 1) {
throw new \Exception('The maximum name length cannot be less than 1 character.');
}
$newName = $name;
// Make sure that the string is no more than the max length
if ($maxLength !== -1 && strlen($newName) > $maxLength) {
$newName = substr($newName, 0, $maxLength);
}
// Logically, the name should at most need to be adjusted once per listed name.
for ($i = 0; $i < count($names); $i++) {
if (!in_array($newName, $names)) {
break;
}
$newName = self::incrementNameWithNumericalSuffix($newName, $maxLength);
}
return $newName;
}
}
|