mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 16:52:41 +01:00
Convert Maniphest custom config to new config types
Summary: Fixes T12870. Ref T12845. Technically, this addresses the core issue in T12845 too, but I'm going to convert the rest of the `custom:...` types before closing that. In particular, for T12870: - Validates that keywords are unique across priorities. - Fixes missing newline in documentation. - Updates documentation to note that keywords are now mandatory and must be unique across priorities. Test Plan: Edited, deleted and mangled all the Maniphest custom options (priorities, statuses, points, subtypes). Reviewers: chad, amckinley Reviewed By: amckinley Maniphest Tasks: T12870, T12845 Differential Revision: https://secure.phabricator.com/D18165
This commit is contained in:
parent
a14b82d4f4
commit
6984d239b0
12 changed files with 120 additions and 83 deletions
|
@ -1488,8 +1488,8 @@ phutil_register_library_map(array(
|
||||||
'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php',
|
'ManiphestHovercardEngineExtension' => 'applications/maniphest/engineextension/ManiphestHovercardEngineExtension.php',
|
||||||
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
|
'ManiphestInfoConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestInfoConduitAPIMethod.php',
|
||||||
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
|
'ManiphestNameIndex' => 'applications/maniphest/storage/ManiphestNameIndex.php',
|
||||||
'ManiphestPointsConfigOptionType' => 'applications/maniphest/config/ManiphestPointsConfigOptionType.php',
|
'ManiphestPointsConfigType' => 'applications/maniphest/config/ManiphestPointsConfigType.php',
|
||||||
'ManiphestPriorityConfigOptionType' => 'applications/maniphest/config/ManiphestPriorityConfigOptionType.php',
|
'ManiphestPrioritiesConfigType' => 'applications/maniphest/config/ManiphestPrioritiesConfigType.php',
|
||||||
'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php',
|
'ManiphestPriorityEmailCommand' => 'applications/maniphest/command/ManiphestPriorityEmailCommand.php',
|
||||||
'ManiphestPrioritySearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestPrioritySearchConduitAPIMethod.php',
|
'ManiphestPrioritySearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestPrioritySearchConduitAPIMethod.php',
|
||||||
'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php',
|
'ManiphestProjectNameFulltextEngineExtension' => 'applications/maniphest/engineextension/ManiphestProjectNameFulltextEngineExtension.php',
|
||||||
|
@ -1500,11 +1500,11 @@ phutil_register_library_map(array(
|
||||||
'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php',
|
'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php',
|
||||||
'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php',
|
'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php',
|
||||||
'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php',
|
'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php',
|
||||||
'ManiphestStatusConfigOptionType' => 'applications/maniphest/config/ManiphestStatusConfigOptionType.php',
|
|
||||||
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
|
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
|
||||||
'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php',
|
'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php',
|
||||||
|
'ManiphestStatusesConfigType' => 'applications/maniphest/config/ManiphestStatusesConfigType.php',
|
||||||
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
|
'ManiphestSubpriorityController' => 'applications/maniphest/controller/ManiphestSubpriorityController.php',
|
||||||
'ManiphestSubtypesConfigOptionsType' => 'applications/maniphest/config/ManiphestSubtypesConfigOptionsType.php',
|
'ManiphestSubtypesConfigType' => 'applications/maniphest/config/ManiphestSubtypesConfigType.php',
|
||||||
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
|
'ManiphestTask' => 'applications/maniphest/storage/ManiphestTask.php',
|
||||||
'ManiphestTaskAssignHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php',
|
'ManiphestTaskAssignHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignHeraldAction.php',
|
||||||
'ManiphestTaskAssignOtherHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php',
|
'ManiphestTaskAssignOtherHeraldAction' => 'applications/maniphest/herald/ManiphestTaskAssignOtherHeraldAction.php',
|
||||||
|
@ -6603,8 +6603,8 @@ phutil_register_library_map(array(
|
||||||
'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
|
'ManiphestHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
|
||||||
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
'ManiphestInfoConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||||
'ManiphestNameIndex' => 'ManiphestDAO',
|
'ManiphestNameIndex' => 'ManiphestDAO',
|
||||||
'ManiphestPointsConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
'ManiphestPointsConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'ManiphestPriorityConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
'ManiphestPrioritiesConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand',
|
'ManiphestPriorityEmailCommand' => 'ManiphestEmailCommand',
|
||||||
'ManiphestPrioritySearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
'ManiphestPrioritySearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||||
'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
'ManiphestProjectNameFulltextEngineExtension' => 'PhabricatorFulltextEngineExtension',
|
||||||
|
@ -6615,11 +6615,11 @@ phutil_register_library_map(array(
|
||||||
'ManiphestReportController' => 'ManiphestController',
|
'ManiphestReportController' => 'ManiphestController',
|
||||||
'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
|
||||||
'ManiphestStatusConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
|
||||||
'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand',
|
'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand',
|
||||||
'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||||
|
'ManiphestStatusesConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'ManiphestSubpriorityController' => 'ManiphestController',
|
'ManiphestSubpriorityController' => 'ManiphestController',
|
||||||
'ManiphestSubtypesConfigOptionsType' => 'PhabricatorConfigJSONOptionType',
|
'ManiphestSubtypesConfigType' => 'PhabricatorJSONConfigType',
|
||||||
'ManiphestTask' => array(
|
'ManiphestTask' => array(
|
||||||
'ManiphestDAO',
|
'ManiphestDAO',
|
||||||
'PhabricatorSubscribableInterface',
|
'PhabricatorSubscribableInterface',
|
||||||
|
|
|
@ -290,6 +290,11 @@ final class PhabricatorConfigEditController
|
||||||
} catch (PhabricatorConfigValidationException $ex) {
|
} catch (PhabricatorConfigValidationException $ex) {
|
||||||
$errors[] = $ex->getMessage();
|
$errors[] = $ex->getMessage();
|
||||||
$xaction = null;
|
$xaction = null;
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
// NOTE: Some older validators throw bare exceptions. Purely in good
|
||||||
|
// taste, it would be nice to convert these at some point.
|
||||||
|
$errors[] = $ex->getMessage();
|
||||||
|
$xaction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestPointsConfigOptionType
|
|
||||||
extends PhabricatorConfigJSONOptionType {
|
|
||||||
|
|
||||||
public function validateOption(PhabricatorConfigOption $option, $value) {
|
|
||||||
ManiphestTaskPoints::validateConfiguration($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestPointsConfigType
|
||||||
|
extends PhabricatorJSONConfigType {
|
||||||
|
|
||||||
|
const TYPEKEY = 'maniphest.points';
|
||||||
|
|
||||||
|
public function validateStoredValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
ManiphestTaskPoints::validateConfiguration($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestPrioritiesConfigType
|
||||||
|
extends PhabricatorJSONConfigType {
|
||||||
|
|
||||||
|
const TYPEKEY = 'maniphest.priorities';
|
||||||
|
|
||||||
|
public function validateStoredValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
ManiphestTaskPriority::validateConfiguration($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestPriorityConfigOptionType
|
|
||||||
extends PhabricatorConfigJSONOptionType {
|
|
||||||
|
|
||||||
public function validateOption(PhabricatorConfigOption $option, $value) {
|
|
||||||
ManiphestTaskPriority::validateConfiguration($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestStatusConfigOptionType
|
|
||||||
extends PhabricatorConfigJSONOptionType {
|
|
||||||
|
|
||||||
public function validateOption(PhabricatorConfigOption $option, $value) {
|
|
||||||
ManiphestTaskStatus::validateConfiguration($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestStatusesConfigType
|
||||||
|
extends PhabricatorJSONConfigType {
|
||||||
|
|
||||||
|
const TYPEKEY = 'maniphest.statuses';
|
||||||
|
|
||||||
|
public function validateStoredValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
ManiphestTaskStatus::validateConfiguration($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
final class ManiphestSubtypesConfigOptionsType
|
|
||||||
extends PhabricatorConfigJSONOptionType {
|
|
||||||
|
|
||||||
public function validateOption(PhabricatorConfigOption $option, $value) {
|
|
||||||
PhabricatorEditEngineSubtype::validateConfiguration($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ManiphestSubtypesConfigType
|
||||||
|
extends PhabricatorJSONConfigType {
|
||||||
|
|
||||||
|
const TYPEKEY = 'maniphest.subtypes';
|
||||||
|
|
||||||
|
public function validateStoredValue(
|
||||||
|
PhabricatorConfigOption $option,
|
||||||
|
$value) {
|
||||||
|
PhabricatorEditEngineSubtype::validateConfiguration($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,47 +20,47 @@ final class PhabricatorManiphestConfigOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOptions() {
|
public function getOptions() {
|
||||||
$priority_type = 'custom:ManiphestPriorityConfigOptionType';
|
$priority_type = 'maniphest.priorities';
|
||||||
$priority_defaults = array(
|
$priority_defaults = array(
|
||||||
100 => array(
|
100 => array(
|
||||||
'name' => pht('Unbreak Now!'),
|
'name' => pht('Unbreak Now!'),
|
||||||
|
'keywords' => array('unbreak'),
|
||||||
'short' => pht('Unbreak!'),
|
'short' => pht('Unbreak!'),
|
||||||
'color' => 'pink',
|
'color' => 'pink',
|
||||||
'keywords' => array('unbreak'),
|
|
||||||
),
|
),
|
||||||
90 => array(
|
90 => array(
|
||||||
'name' => pht('Needs Triage'),
|
'name' => pht('Needs Triage'),
|
||||||
|
'keywords' => array('triage'),
|
||||||
'short' => pht('Triage'),
|
'short' => pht('Triage'),
|
||||||
'color' => 'violet',
|
'color' => 'violet',
|
||||||
'keywords' => array('triage'),
|
|
||||||
),
|
),
|
||||||
80 => array(
|
80 => array(
|
||||||
'name' => pht('High'),
|
'name' => pht('High'),
|
||||||
|
'keywords' => array('high'),
|
||||||
'short' => pht('High'),
|
'short' => pht('High'),
|
||||||
'color' => 'red',
|
'color' => 'red',
|
||||||
'keywords' => array('high'),
|
|
||||||
),
|
),
|
||||||
50 => array(
|
50 => array(
|
||||||
'name' => pht('Normal'),
|
'name' => pht('Normal'),
|
||||||
|
'keywords' => array('normal'),
|
||||||
'short' => pht('Normal'),
|
'short' => pht('Normal'),
|
||||||
'color' => 'orange',
|
'color' => 'orange',
|
||||||
'keywords' => array('normal'),
|
|
||||||
),
|
),
|
||||||
25 => array(
|
25 => array(
|
||||||
'name' => pht('Low'),
|
'name' => pht('Low'),
|
||||||
|
'keywords' => array('low'),
|
||||||
'short' => pht('Low'),
|
'short' => pht('Low'),
|
||||||
'color' => 'yellow',
|
'color' => 'yellow',
|
||||||
'keywords' => array('low'),
|
|
||||||
),
|
),
|
||||||
0 => array(
|
0 => array(
|
||||||
'name' => pht('Wishlist'),
|
'name' => pht('Wishlist'),
|
||||||
|
'keywords' => array('wish', 'wishlist'),
|
||||||
'short' => pht('Wish'),
|
'short' => pht('Wish'),
|
||||||
'color' => 'sky',
|
'color' => 'sky',
|
||||||
'keywords' => array('wish', 'wishlist'),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
$status_type = 'custom:ManiphestStatusConfigOptionType';
|
$status_type = 'maniphest.statuses';
|
||||||
$status_defaults = array(
|
$status_defaults = array(
|
||||||
'open' => array(
|
'open' => array(
|
||||||
'name' => pht('Open'),
|
'name' => pht('Open'),
|
||||||
|
@ -265,7 +265,7 @@ EOTEXT
|
||||||
);
|
);
|
||||||
$fields_json = id(new PhutilJSON())->encodeFormatted($fields_example);
|
$fields_json = id(new PhutilJSON())->encodeFormatted($fields_example);
|
||||||
|
|
||||||
$points_type = 'custom:ManiphestPointsConfigOptionType';
|
$points_type = 'maniphest.points';
|
||||||
|
|
||||||
$points_example_1 = array(
|
$points_example_1 = array(
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
|
@ -299,7 +299,7 @@ See the example below for a starting point.
|
||||||
EOTEXT
|
EOTEXT
|
||||||
));
|
));
|
||||||
|
|
||||||
$subtype_type = 'custom:ManiphestSubtypesConfigOptionsType';
|
$subtype_type = 'maniphest.subtypes';
|
||||||
$subtype_default_key = PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT;
|
$subtype_default_key = PhabricatorEditEngineSubtype::SUBTYPE_DEFAULT;
|
||||||
$subtype_example = array(
|
$subtype_example = array(
|
||||||
array(
|
array(
|
||||||
|
@ -349,6 +349,32 @@ EOTEXT
|
||||||
,
|
,
|
||||||
$subtype_default_key));
|
$subtype_default_key));
|
||||||
|
|
||||||
|
$priorities_description = $this->deformat(pht(<<<EOTEXT
|
||||||
|
Allows you to edit or override the default priorities available in Maniphest,
|
||||||
|
like "High", "Normal" and "Low". The configuration should contain a map of
|
||||||
|
numeric priority values (where larger numbers correspond to higher priorities)
|
||||||
|
to priority specifications (see defaults below for examples).
|
||||||
|
|
||||||
|
The keys you can define for a priority are:
|
||||||
|
|
||||||
|
- `name` //Required string.// Name of the priority.
|
||||||
|
- `keywords` //Required list<string>.// List of unique keywords which identify
|
||||||
|
this priority, like "high" or "low". Each priority must have at least one
|
||||||
|
keyword and two priorities may not share the same keyword.
|
||||||
|
- `short` //Optional string.// Alternate shorter name, used in UIs where
|
||||||
|
there is less space available.
|
||||||
|
- `color` //Optional string.// Color for this priority, like "red" or
|
||||||
|
"blue".
|
||||||
|
- `disabled` //Optional bool.// Set to true to prevent users from choosing
|
||||||
|
this priority when creating or editing tasks. Existing tasks will not be
|
||||||
|
affected, and can be batch edited to a different priority or left to
|
||||||
|
eventually die out.
|
||||||
|
|
||||||
|
You can choose the default priority for newly created tasks with
|
||||||
|
"maniphest.default-priority".
|
||||||
|
EOTEXT
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
$this->newOption('maniphest.custom-field-definitions', 'wild', array())
|
$this->newOption('maniphest.custom-field-definitions', 'wild', array())
|
||||||
|
@ -367,30 +393,7 @@ EOTEXT
|
||||||
$priority_type,
|
$priority_type,
|
||||||
$priority_defaults)
|
$priority_defaults)
|
||||||
->setSummary(pht('Configure Maniphest priority names.'))
|
->setSummary(pht('Configure Maniphest priority names.'))
|
||||||
->setDescription(
|
->setDescription($priorities_description),
|
||||||
pht(
|
|
||||||
'Allows you to edit or override the default priorities available '.
|
|
||||||
'in Maniphest, like "High", "Normal" and "Low". The configuration '.
|
|
||||||
'should contain a map of priority constants to priority '.
|
|
||||||
'specifications (see defaults below for examples).'.
|
|
||||||
"\n\n".
|
|
||||||
'The keys you can define for a priority are:'.
|
|
||||||
"\n\n".
|
|
||||||
' - `name` Name of the priority.'."\n".
|
|
||||||
' - `short` Alternate shorter name, used in UIs where there is '.
|
|
||||||
' not much space available.'."\n".
|
|
||||||
' - `color` A color for this priority, like "red" or "blue".'.
|
|
||||||
' - `keywords` An optional list of keywords which can '.
|
|
||||||
' be used to select this priority when using `!priority` '.
|
|
||||||
' commands in email.'."\n".
|
|
||||||
' - `disabled` Optional boolean to prevent users from choosing '.
|
|
||||||
' this priority when creating or editing tasks. Existing '.
|
|
||||||
' tasks will be unaffected, and can be batch edited to a '.
|
|
||||||
' different priority or left to eventually die out.'.
|
|
||||||
"\n\n".
|
|
||||||
'You can choose which priority is the default for newly created '.
|
|
||||||
'tasks with `%s`.',
|
|
||||||
'maniphest.default-priority')),
|
|
||||||
$this->newOption('maniphest.statuses', $status_type, $status_defaults)
|
$this->newOption('maniphest.statuses', $status_type, $status_defaults)
|
||||||
->setSummary(pht('Configure Maniphest task statuses.'))
|
->setSummary(pht('Configure Maniphest task statuses.'))
|
||||||
->setDescription($status_description)
|
->setDescription($status_description)
|
||||||
|
|
|
@ -203,6 +203,7 @@ final class ManiphestTaskPriority extends ManiphestConstants {
|
||||||
$config));
|
$config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$all_keywords = array();
|
||||||
foreach ($config as $key => $value) {
|
foreach ($config as $key => $value) {
|
||||||
if (!ctype_digit((string)$key)) {
|
if (!ctype_digit((string)$key)) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
|
@ -223,9 +224,9 @@ final class ManiphestTaskPriority extends ManiphestConstants {
|
||||||
$value,
|
$value,
|
||||||
array(
|
array(
|
||||||
'name' => 'string',
|
'name' => 'string',
|
||||||
|
'keywords' => 'list<string>',
|
||||||
'short' => 'optional string',
|
'short' => 'optional string',
|
||||||
'color' => 'optional string',
|
'color' => 'optional string',
|
||||||
'keywords' => 'list<string>',
|
|
||||||
'disabled' => 'optional bool',
|
'disabled' => 'optional bool',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -242,6 +243,18 @@ final class ManiphestTaskPriority extends ManiphestConstants {
|
||||||
'low',
|
'low',
|
||||||
'critical'));
|
'critical'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($all_keywords[$keyword])) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Two different task priorities ("%s" and "%s") have the same '.
|
||||||
|
'keyword ("%s"). Keywords must uniquely identify priorities.',
|
||||||
|
$value['name'],
|
||||||
|
$all_keywords[$keyword],
|
||||||
|
$keyword));
|
||||||
|
}
|
||||||
|
|
||||||
|
$all_keywords[$keyword] = $value['name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue