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
6 changes: 6 additions & 0 deletions apps/theming/css/theming.scss
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,9 @@ input.primary,
border: 1px solid #ebebeb;
}
}

@if ($has-legal-links == 'true') {
footer {
height: 92px;
}
}
3 changes: 2 additions & 1 deletion apps/theming/js/settings-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ function hideUndoButton(setting, value) {
color: '#0082c9',
logoMime: '',
backgroundMime: '',
imprintUrl: ''
imprintUrl: '',
privacyUrl: ''
};

if (value === themingDefaults[setting] || value === '') {
Expand Down
11 changes: 11 additions & 0 deletions apps/theming/lib/Controller/ThemingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ public function updateStylesheet($setting, $value) {
]);
}
break;
case 'privacyUrl':
if (strlen($value) > 500) {
return new DataResponse([
'data' => [
'message' => $this->l10n->t('The given privacy policy address is too long'),
],
'status' => 'error'
]);
}
break;
case 'slogan':
if (strlen($value) > 500) {
return new DataResponse([
Expand Down Expand Up @@ -419,6 +429,7 @@ public function getJavascript() {
slogan: ' . json_encode($this->themingDefaults->getSlogan()) . ',
color: ' . json_encode($this->themingDefaults->getColorPrimary()) . ',
imprintUrl: ' . json_encode($this->themingDefaults->getImprintUrl()) . ',
privacyUrl: ' . json_encode($this->themingDefaults->getPrivacyUrl()) . ',
inverted: ' . json_encode($this->util->invertTextColor($this->themingDefaults->getColorPrimary())) . ',
cacheBuster: ' . json_encode($cacheBusterValue) . '
};
Expand Down
1 change: 1 addition & 0 deletions apps/theming/lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public function getForm(): TemplateResponse {
'iconDocs' => $this->urlGenerator->linkToDocs('admin-theming-icons'),
'images' => $this->imageManager->getCustomImages(),
'imprintUrl' => $this->themingDefaults->getImprintUrl(),
'privacyUrl' => $this->themingDefaults->getPrivacyUrl(),
];

return new TemplateResponse('theming', 'settings-admin', $parameters, '');
Expand Down
45 changes: 36 additions & 9 deletions apps/theming/lib/ThemingDefaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ public function getSlogan() {
}

public function getImprintUrl() {
return $this->config->getAppValue('theming', 'imprintUrl', '');
return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
}

public function getPrivacyUrl() {
return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
}

public function getShortFooter() {
Expand All @@ -151,14 +155,31 @@ public function getShortFooter() {
' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
($slogan !== '' ? ' – ' . $slogan : '');

$imprintUrl = (string)$this->getImprintUrl();
if($imprintUrl !== ''
&& filter_var($imprintUrl, FILTER_VALIDATE_URL, [
'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
])
) {
$footer .= '<br/><a href="' . $imprintUrl . '" class="legal" target="_blank"' .
' rel="noreferrer noopener">' . $this->l->t('Legal notice') . '</a>';
$links = [
[
'text' => $this->l->t('Legal notice'),
'url' => (string)$this->getImprintUrl()
],
[
'text' => $this->l->t('Privacy policy'),
'url' => (string)$this->getPrivacyUrl()
],
];

$legalLinks = ''; $divider = '';
foreach($links as $link) {
if($link['url'] !== ''
&& filter_var($link['url'], FILTER_VALIDATE_URL, [
'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
])
) {
$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
' rel="noreferrer noopener">' . $link['text'] . '</a>';
$divider = ' · ';
}
}
if($legalLinks !== '' ) {
$footer .= '<br/>' . $legalLinks;
}

return $footer;
Expand Down Expand Up @@ -266,6 +287,12 @@ public function getScssVariables() {
if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') {
$variables['image-login-plain'] = 'true';
}

$variables['has-legal-links'] = 'false';
if($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
$variables['has-legal-links'] = 'true';
}

$cache->set('getScssVariables', $variables);
return $variables;
}
Expand Down
9 changes: 8 additions & 1 deletion apps/theming/templates/settings-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,16 @@
<div class="advanced-options">
<div>
<label>
<span><?php p($l->t('Legal notice link')) ?></span>
<span><?php p($l->t('Legal notice link')) ?></span>
<input id="theming-imprintUrl" type="url" placeholder="<?php p($l->t('https://…')); ?>" value="<?php p($_['imprintUrl']) ?>" maxlength="500" />
<div data-setting="imprintUrl" data-toggle="tooltip" data-original-title="<?php p($l->t('Reset to default')); ?>" class="theme-undo icon icon-history"></div>
</label>
</div>
<div>
<label>
<span><?php p($l->t('Privacy policy link')) ?></span>
<input id="theming-privacyUrl" type="url" placeholder="<?php p($l->t('https://…')); ?>" value="<?php p($_['privacyUrl']) ?>" maxlength="500" />
<div data-setting="privacyUrl" data-toggle="tooltip" data-original-title="<?php p($l->t('Reset to default')); ?>" class="theme-undo icon icon-history"></div>
</label>
</div>
<div class="advanced-option-logoheader">
Expand Down
2 changes: 2 additions & 0 deletions apps/theming/tests/Controller/ThemingControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,7 @@ public function testGetJavascript() {
slogan: "",
color: "#000",
imprintUrl: null,
privacyUrl: null,
inverted: false,
cacheBuster: null
};
Expand Down Expand Up @@ -853,6 +854,7 @@ public function testGetJavascriptInverted() {
slogan: "awesome",
color: "#ffffff",
imprintUrl: null,
privacyUrl: null,
inverted: true,
cacheBuster: null
};
Expand Down
10 changes: 10 additions & 0 deletions apps/theming/tests/Settings/AdminTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ public function testGetFormNoErrors() {
->expects($this->once())
->method('getImprintUrl')
->willReturn('');
$this->themingDefaults
->expects($this->once())
->method('getPrivacyUrl')
->willReturn('');
$this->themingDefaults
->expects($this->once())
->method('getSlogan')
Expand All @@ -110,6 +114,7 @@ public function testGetFormNoErrors() {
'iconDocs' => null,
'images' => [],
'imprintUrl' => '',
'privacyUrl' => '',
];

$expected = new TemplateResponse('theming', 'settings-admin', $params, '');
Expand Down Expand Up @@ -139,6 +144,10 @@ public function testGetFormWithErrors() {
->expects($this->once())
->method('getImprintUrl')
->willReturn('');
$this->themingDefaults
->expects($this->once())
->method('getPrivacyUrl')
->willReturn('');
$this->themingDefaults
->expects($this->once())
->method('getSlogan')
Expand All @@ -164,6 +173,7 @@ public function testGetFormWithErrors() {
'iconDocs' => '',
'images' => [],
'imprintUrl' => '',
'privacyUrl' => '',
];

$expected = new TemplateResponse('theming', 'settings-admin', $params, '');
Expand Down
102 changes: 90 additions & 12 deletions apps/theming/tests/ThemingDefaultsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,16 +195,16 @@ public function testGetBaseUrlWithCustom() {
$this->assertEquals('https://example.com/', $this->template->getBaseUrl());
}

public function imprintUrlProvider() {
public function legalUrlProvider() {
return [
[ '' ],
[ 'https://example.com/imprint.html']
[ 'https://example.com/legal.html']
];
}

/**
* @param $imprintUrl
* @dataProvider imprintUrlProvider
* @dataProvider legalUrlProvider
*/
public function testGetImprintURL($imprintUrl) {
$this->config
Expand All @@ -216,6 +216,20 @@ public function testGetImprintURL($imprintUrl) {
$this->assertEquals($imprintUrl, $this->template->getImprintUrl());
}

/**
* @param $privacyUrl
* @dataProvider legalUrlProvider
*/
public function testGetPrivacyURL($privacyUrl) {
$this->config
->expects($this->once())
->method('getAppValue')
->with('theming', 'privacyUrl', '')
->willReturn($privacyUrl);

$this->assertEquals($privacyUrl, $this->template->getPrivacyUrl());
}

public function testGetSloganWithDefault() {
$this->config
->expects($this->once())
Expand All @@ -238,41 +252,44 @@ public function testGetSloganWithCustom() {

public function testGetShortFooter() {
$this->config
->expects($this->exactly(4))
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan', $this->template->getShortFooter());
}

public function testGetShortFooterEmptySlogan() {
$this->config
->expects($this->exactly(4))
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), ''],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a>', $this->template->getShortFooter());
}

public function testGetShortFooterImprint() {
$this->config
->expects($this->exactly(4))
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'imprintUrl', '', 'https://example.com/imprint'],
['theming', 'privacyUrl', '', ''],
]);

$this->l10n
Expand All @@ -283,26 +300,86 @@ public function testGetShortFooterImprint() {
$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a>', $this->template->getShortFooter());
}

public function invalidImprintUrlProvider() {
public function testGetShortFooterPrivacy() {
$this->config
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', 'https://example.com/privacy'],
]);

$this->l10n
->expects($this->any())
->method('t')
->willReturnArgument(0);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan<br/><a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a>', $this->template->getShortFooter());
}

public function testGetShortFooterAllLegalLinks() {
$this->config
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'imprintUrl', '', 'https://example.com/imprint'],
['theming', 'privacyUrl', '', 'https://example.com/privacy'],
]);

$this->l10n
->expects($this->any())
->method('t')
->willReturnArgument(0);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a> · <a href="https://example.com/privacy" class="legal" target="_blank" rel="noreferrer noopener">Privacy policy</a>', $this->template->getShortFooter());
}

public function invalidLegalUrlProvider() {
return [
['example.com/imprint'], # missing scheme
['https:///imprint'], # missing host
['example.com/legal'], # missing scheme
['https:///legal'], # missing host
];
}

/**
* @param $invalidImprintUrl
* @dataProvider invalidImprintUrlProvider
* @dataProvider invalidLegalUrlProvider
*/
public function testGetShortFooterInvalidImprint($invalidImprintUrl) {
$this->config
->expects($this->exactly(4))
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'imprintUrl', '', $invalidImprintUrl],
['theming', 'privacyUrl', '', ''],
]);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan', $this->template->getShortFooter());
}

/**
* @param $invalidPrivacyUrl
* @dataProvider invalidLegalUrlProvider
*/
public function testGetShortFooterInvalidPrivacy($invalidPrivacyUrl) {
$this->config
->expects($this->exactly(5))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', $invalidPrivacyUrl],
]);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan', $this->template->getShortFooter());
Expand Down Expand Up @@ -577,7 +654,8 @@ public function testGetScssVariables() {
'theming-logoheader-mime' => '\'jpeg\'',
'theming-favicon-mime' => '\'jpeg\'',
'image-logoheader' => '\'custom-logoheader?v=0\'',
'image-favicon' => '\'custom-favicon?v=0\''
'image-favicon' => '\'custom-favicon?v=0\'',
'has-legal-links' => 'false'
];
$this->assertEquals($expected, $this->template->getScssVariables());
}
Expand Down