2011-03-22 22:34:38 +01:00
|
|
|
<?php
|
|
|
|
|
2012-03-10 00:46:25 +01:00
|
|
|
final class HeraldNewController extends HeraldController {
|
2011-03-22 22:34:38 +01:00
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
$request = $this->getRequest();
|
2013-12-31 01:48:14 +01:00
|
|
|
$viewer = $request->getUser();
|
2011-03-22 22:34:38 +01:00
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
$content_type_map = HeraldAdapter::getEnabledAdapterMap($viewer);
|
2013-12-27 22:16:25 +01:00
|
|
|
$rule_type_map = HeraldRuleTypeConfig::getRuleTypeMap();
|
|
|
|
|
|
|
|
$errors = array();
|
|
|
|
|
|
|
|
$e_type = null;
|
|
|
|
$e_rule = null;
|
2013-12-31 01:48:14 +01:00
|
|
|
$e_object = null;
|
2013-12-27 22:16:25 +01:00
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
$step = $request->getInt('step');
|
2013-12-27 22:16:25 +01:00
|
|
|
if ($request->isFormPost()) {
|
|
|
|
$content_type = $request->getStr('content_type');
|
|
|
|
if (empty($content_type_map[$content_type])) {
|
|
|
|
$errors[] = pht('You must choose a content type for this rule.');
|
|
|
|
$e_type = pht('Required');
|
|
|
|
$step = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors && $step > 1) {
|
|
|
|
$rule_type = $request->getStr('rule_type');
|
|
|
|
if (empty($rule_type_map[$rule_type])) {
|
|
|
|
$errors[] = pht('You must choose a rule type for this rule.');
|
|
|
|
$e_rule = pht('Required');
|
|
|
|
$step = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
if (!$errors && $step >= 2) {
|
|
|
|
$target_phid = null;
|
|
|
|
$object_name = $request->getStr('objectName');
|
|
|
|
$done = false;
|
|
|
|
if ($rule_type != HeraldRuleTypeConfig::RULE_TYPE_OBJECT) {
|
|
|
|
$done = true;
|
|
|
|
} else if (strlen($object_name)) {
|
|
|
|
$target_object = id(new PhabricatorObjectQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withNames(array($object_name))
|
|
|
|
->executeOne();
|
|
|
|
if ($target_object) {
|
|
|
|
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
|
|
|
$viewer,
|
|
|
|
$target_object,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT);
|
|
|
|
if (!$can_edit) {
|
|
|
|
$errors[] = pht(
|
|
|
|
'You can not create a rule for that object, because you do '.
|
|
|
|
'not have permission to edit it. You can only create rules '.
|
|
|
|
'for objects you can edit.');
|
|
|
|
$e_object = pht('Not Editable');
|
|
|
|
$step = 2;
|
|
|
|
} else {
|
|
|
|
$adapter = HeraldAdapter::getAdapterForContentType($content_type);
|
|
|
|
if (!$adapter->canTriggerOnObject($target_object)) {
|
|
|
|
$errors[] = pht(
|
|
|
|
'This object is not of an allowed type for the rule. '.
|
|
|
|
'Rules can only trigger on certain objects.');
|
|
|
|
$e_object = pht('Invalid');
|
|
|
|
$step = 2;
|
|
|
|
} else {
|
|
|
|
$target_phid = $target_object->getPHID();
|
|
|
|
$done = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$errors[] = pht('No object exists by that name.');
|
|
|
|
$e_object = pht('Invalid');
|
|
|
|
$step = 2;
|
|
|
|
}
|
|
|
|
} else if ($step > 2) {
|
|
|
|
$errors[] = pht(
|
|
|
|
'You must choose an object to associate this rule with.');
|
|
|
|
$e_object = pht('Required');
|
|
|
|
$step = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors && $done) {
|
|
|
|
$uri = id(new PhutilURI('edit/'))
|
|
|
|
->setQueryParams(
|
|
|
|
array(
|
|
|
|
'content_type' => $content_type,
|
|
|
|
'rule_type' => $rule_type,
|
|
|
|
'targetPHID' => $target_phid,
|
|
|
|
));
|
|
|
|
$uri = $this->getApplicationURI($uri);
|
|
|
|
return id(new AphrontRedirectResponse())->setURI($uri);
|
|
|
|
}
|
2013-12-27 22:16:25 +01:00
|
|
|
}
|
2011-03-22 22:34:38 +01:00
|
|
|
}
|
|
|
|
|
2013-12-31 01:48:14 +01:00
|
|
|
$content_type = $request->getStr('content_type');
|
|
|
|
$rule_type = $request->getStr('rule_type');
|
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
$form = id(new AphrontFormView())
|
2013-12-31 01:48:14 +01:00
|
|
|
->setUser($viewer)
|
2013-12-27 22:16:25 +01:00
|
|
|
->setAction($this->getApplicationURI('new/'));
|
|
|
|
|
|
|
|
switch ($step) {
|
|
|
|
case 0:
|
|
|
|
default:
|
2013-12-31 01:48:07 +01:00
|
|
|
$content_types = $this->renderContentTypeControl(
|
|
|
|
$content_type_map,
|
|
|
|
$e_type);
|
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
$form
|
|
|
|
->addHiddenInput('step', 1)
|
2013-12-27 22:16:33 +01:00
|
|
|
->appendChild($content_types);
|
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
$cancel_text = null;
|
|
|
|
$cancel_uri = $this->getApplicationURI();
|
|
|
|
break;
|
|
|
|
case 1:
|
2013-12-31 01:48:07 +01:00
|
|
|
$rule_types = $this->renderRuleTypeControl(
|
|
|
|
$rule_type_map,
|
|
|
|
$e_rule);
|
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
$form
|
2013-12-31 01:48:14 +01:00
|
|
|
->addHiddenInput('content_type', $content_type)
|
2013-12-27 22:16:25 +01:00
|
|
|
->addHiddenInput('step', 2)
|
2013-12-27 22:16:33 +01:00
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel(pht('Rule for'))
|
|
|
|
->setValue(
|
|
|
|
phutil_tag(
|
|
|
|
'strong',
|
|
|
|
array(),
|
|
|
|
idx($content_type_map, $content_type))))
|
2013-12-27 22:16:25 +01:00
|
|
|
->appendChild($rule_types);
|
2013-12-27 22:16:33 +01:00
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
$cancel_text = pht('Back');
|
|
|
|
$cancel_uri = id(new PhutilURI('new/'))
|
|
|
|
->setQueryParams(
|
|
|
|
array(
|
2013-12-31 01:48:14 +01:00
|
|
|
'content_type' => $content_type,
|
|
|
|
'step' => 0,
|
|
|
|
));
|
|
|
|
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
$adapter = HeraldAdapter::getAdapterForContentType($content_type);
|
|
|
|
$form
|
|
|
|
->addHiddenInput('content_type', $content_type)
|
|
|
|
->addHiddenInput('rule_type', $rule_type)
|
|
|
|
->addHiddenInput('step', 3)
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel(pht('Rule for'))
|
|
|
|
->setValue(
|
|
|
|
phutil_tag(
|
|
|
|
'strong',
|
|
|
|
array(),
|
|
|
|
idx($content_type_map, $content_type))))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormStaticControl())
|
|
|
|
->setLabel(pht('Rule Type'))
|
|
|
|
->setValue(
|
|
|
|
phutil_tag(
|
|
|
|
'strong',
|
|
|
|
array(),
|
|
|
|
idx($rule_type_map, $rule_type))))
|
|
|
|
->appendRemarkupInstructions(
|
|
|
|
pht(
|
|
|
|
'Choose the object this rule will act on (for example, enter '.
|
2014-01-03 21:24:28 +01:00
|
|
|
'`rX` to act on the `rX` repository, or `#project` to act on '.
|
|
|
|
'a project).'))
|
2013-12-31 01:48:14 +01:00
|
|
|
->appendRemarkupInstructions(
|
|
|
|
$adapter->explainValidTriggerObjects())
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTextControl())
|
|
|
|
->setName('objectName')
|
|
|
|
->setError($e_object)
|
|
|
|
->setValue($request->getStr('objectName'))
|
|
|
|
->setLabel(pht('Object')));
|
|
|
|
|
|
|
|
$cancel_text = pht('Back');
|
|
|
|
$cancel_uri = id(new PhutilURI('new/'))
|
|
|
|
->setQueryParams(
|
|
|
|
array(
|
|
|
|
'content_type' => $content_type,
|
|
|
|
'rule_type' => $rule_type,
|
2013-12-27 22:16:25 +01:00
|
|
|
'step' => 1,
|
|
|
|
));
|
|
|
|
$cancel_uri = $this->getApplicationURI($cancel_uri);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$form
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->setValue(pht('Continue'))
|
|
|
|
->addCancelButton($cancel_uri, $cancel_text));
|
|
|
|
|
|
|
|
$form_box = id(new PHUIObjectBoxView())
|
2014-01-10 18:17:37 +01:00
|
|
|
->setFormErrors($errors)
|
2013-12-27 22:16:25 +01:00
|
|
|
->setHeaderText(pht('Create Herald Rule'))
|
|
|
|
->setForm($form);
|
|
|
|
|
|
|
|
$crumbs = $this
|
|
|
|
->buildApplicationCrumbs()
|
|
|
|
->addTextCrumb(pht('Create Rule'));
|
|
|
|
|
|
|
|
return $this->buildApplicationPage(
|
|
|
|
array(
|
|
|
|
$crumbs,
|
|
|
|
$form_box,
|
|
|
|
),
|
|
|
|
array(
|
|
|
|
'title' => pht('Create Herald Rule'),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2013-12-27 22:16:33 +01:00
|
|
|
private function renderContentTypeControl(array $content_type_map, $e_type) {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
|
|
|
$radio = id(new AphrontFormRadioButtonControl())
|
|
|
|
->setLabel(pht('New Rule for'))
|
|
|
|
->setName('content_type')
|
|
|
|
->setValue($request->getStr('content_type'))
|
|
|
|
->setError($e_type);
|
|
|
|
|
|
|
|
foreach ($content_type_map as $value => $name) {
|
|
|
|
$adapter = HeraldAdapter::getAdapterForContentType($value);
|
|
|
|
$radio->addButton(
|
|
|
|
$value,
|
|
|
|
$name,
|
|
|
|
phutil_escape_html_newlines($adapter->getAdapterContentDescription()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $radio;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
private function renderRuleTypeControl(array $rule_type_map, $e_rule) {
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
2013-12-27 22:17:10 +01:00
|
|
|
// Reorder array to put less powerful rules first.
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
$rule_type_map = array_select_keys(
|
|
|
|
$rule_type_map,
|
|
|
|
array(
|
|
|
|
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL,
|
2013-12-27 22:17:10 +01:00
|
|
|
HeraldRuleTypeConfig::RULE_TYPE_OBJECT,
|
|
|
|
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL,
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
)) + $rule_type_map;
|
|
|
|
|
2013-10-09 22:52:04 +02:00
|
|
|
list($can_global, $global_link) = $this->explainApplicationCapability(
|
2014-07-25 00:20:39 +02:00
|
|
|
HeraldManageGlobalRulesCapability::CAPABILITY,
|
2013-10-09 22:52:04 +02:00
|
|
|
pht('You have permission to create and manage global rules.'),
|
|
|
|
pht('You do not have permission to create or manage global rules.'));
|
2013-10-05 00:15:48 +02:00
|
|
|
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
$captions = array(
|
|
|
|
HeraldRuleTypeConfig::RULE_TYPE_PERSONAL =>
|
2013-10-05 00:15:48 +02:00
|
|
|
pht(
|
|
|
|
'Personal rules notify you about events. You own them, but they can '.
|
2013-10-05 21:55:34 +02:00
|
|
|
'only affect you. Personal rules only trigger for objects you have '.
|
|
|
|
'permission to see.'),
|
2013-12-31 01:48:14 +01:00
|
|
|
HeraldRuleTypeConfig::RULE_TYPE_OBJECT =>
|
|
|
|
pht(
|
|
|
|
'Object rules notify anyone about events. They are bound to an '.
|
|
|
|
'object (like a repository) and can only act on that object. You '.
|
|
|
|
'must be able to edit an object to create object rules for it. '.
|
2014-03-13 00:12:43 +01:00
|
|
|
'Other users who can edit the object can edit its rules.'),
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
HeraldRuleTypeConfig::RULE_TYPE_GLOBAL =>
|
2013-10-09 22:52:04 +02:00
|
|
|
array(
|
|
|
|
pht(
|
|
|
|
'Global rules notify anyone about events. Global rules can '.
|
|
|
|
'bypass access control policies and act on any object.'),
|
|
|
|
$global_link,
|
|
|
|
),
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
$radio = id(new AphrontFormRadioButtonControl())
|
2013-12-31 01:48:14 +01:00
|
|
|
->setLabel(pht('Rule Type'))
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
->setName('rule_type')
|
2013-12-27 22:16:25 +01:00
|
|
|
->setValue($request->getStr('rule_type'))
|
|
|
|
->setError($e_rule);
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
|
2013-12-31 01:48:07 +01:00
|
|
|
$adapter = HeraldAdapter::getAdapterForContentType(
|
|
|
|
$request->getStr('content_type'));
|
|
|
|
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
foreach ($rule_type_map as $value => $name) {
|
2013-12-31 01:48:07 +01:00
|
|
|
$caption = idx($captions, $value);
|
2013-10-05 00:15:48 +02:00
|
|
|
$disabled = ($value == HeraldRuleTypeConfig::RULE_TYPE_GLOBAL) &&
|
|
|
|
(!$can_global);
|
|
|
|
|
2013-12-31 01:48:07 +01:00
|
|
|
if (!$adapter->supportsRuleType($value)) {
|
|
|
|
$disabled = true;
|
|
|
|
$caption = array(
|
|
|
|
$caption,
|
|
|
|
"\n\n",
|
|
|
|
phutil_tag(
|
|
|
|
'em',
|
|
|
|
array(),
|
|
|
|
pht(
|
|
|
|
'This rule type is not supported by the selected content type.')),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
$radio->addButton(
|
|
|
|
$value,
|
|
|
|
$name,
|
2013-12-31 01:48:07 +01:00
|
|
|
phutil_escape_html_newlines($caption),
|
2013-10-05 00:15:48 +02:00
|
|
|
$disabled ? 'disabled' : null,
|
|
|
|
$disabled);
|
Improve Herald personal/global UI/UX
Summary:
- Default "personal" vs "global" choice to "personal".
- Don't show global rules under "My Rules".
- After editing or creating a global rule, redirect back to global rule list.
- Use radio buttons for "personal" vs "global" and add captions explaining the
difference.
- For "global" rules, don't show the owner/author in the rule detail view --
they effectively have no owner (see also D1387).
- For "global" rules, don't show the owner/author in the rule list view, as
above.
- For admin views, show rule type (global vs personal).
Test Plan:
- Created and edited new global and personal rules.
- Viewed "my", "global" and "admin" views.
Reviewers: btrahan, jungejason, nh, xela
Reviewed By: btrahan
CC: aran, epriestley
Differential Revision: https://secure.phabricator.com/D1518
2012-01-31 21:09:29 +01:00
|
|
|
}
|
|
|
|
|
2013-12-27 22:16:25 +01:00
|
|
|
return $radio;
|
2011-03-22 22:34:38 +01:00
|
|
|
}
|
2014-07-25 00:20:39 +02:00
|
|
|
|
2011-03-22 22:34:38 +01:00
|
|
|
}
|