Skip to content
Open
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
18 changes: 0 additions & 18 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2580,30 +2580,12 @@ parameters:
count: 1
path: tests/lib/RichText/Converter/LinkTest.php

-
message: '#^Parameter \#1 \$locationService of class Ibexa\\FieldTypeRichText\\RichText\\Converter\\Link constructor expects Ibexa\\Contracts\\Core\\Repository\\LocationService, PHPUnit\\Framework\\MockObject\\MockObject given\.$#'
identifier: argument.type
count: 5
path: tests/lib/RichText/Converter/LinkTest.php

-
message: '#^Parameter \#2 \$contentService of class Ibexa\\FieldTypeRichText\\RichText\\Converter\\Link constructor expects Ibexa\\Contracts\\Core\\Repository\\ContentService, PHPUnit\\Framework\\MockObject\\MockObject given\.$#'
identifier: argument.type
count: 5
path: tests/lib/RichText/Converter/LinkTest.php

-
message: '#^Parameter \#2 \$function of class Ibexa\\Core\\Base\\Exceptions\\UnauthorizedException constructor expects string, int given\.$#'
identifier: argument.type
count: 4
path: tests/lib/RichText/Converter/LinkTest.php

-
message: '#^Parameter \#3 \$router of class Ibexa\\FieldTypeRichText\\RichText\\Converter\\Link constructor expects Symfony\\Component\\Routing\\RouterInterface, PHPUnit\\Framework\\MockObject\\MockObject given\.$#'
identifier: argument.type
count: 5
path: tests/lib/RichText/Converter/LinkTest.php

-
message: '#^Call to method expects\(\) on an unknown class Ibexa\\FieldTypeRichText\\RichText\\RendererInterface\.$#'
identifier: class.notFound
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class IbexaEmbedImageEditing extends Plugin {
defineSchema() {
const { schema } = this.editor.model;
const customClassesConfig = getCustomClassesConfig();
const allowedAttributes = ['contentId', 'size', 'ibexaLinkHref', 'ibexaLinkTitle', 'ibexaLinkTarget'];
const allowedAttributes = ['contentId', 'size', 'ibexaLinkHref', 'ibexaLinkTitle', 'ibexaLinkTarget', 'ibexaLinkSiteaccess'];

if (customClassesConfig.link) {
allowedAttributes.push('ibexaLinkClasses');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class IbexaLinkCommand extends Command {
writer.setAttribute('ibexaLinkHref', linkData.href, element);
writer.setAttribute('ibexaLinkTitle', linkData.title, element);
writer.setAttribute('ibexaLinkTarget', linkData.target, element);
writer.setAttribute('ibexaLinkSiteaccess', linkData.siteaccess, element);
writer.setAttribute('ibexaLinkClasses', linkData.ibexaLinkClasses, element);

if (linkData.ibexaLinkAttributes) {
Expand Down
14 changes: 14 additions & 0 deletions src/bundle/Resources/public/js/CKEditor/link/link-editing.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ class IbexaCustomTagEditing extends Plugin {
view: (target, { writer: downcastWriter }) => downcastWriter.createAttributeElement('a', { target }),
});

conversion.for('editingDowncast').attributeToElement({
model: 'ibexaLinkSiteaccess',
view: (siteaccess, { writer: downcastWriter }) => downcastWriter.createAttributeElement('a', { siteaccess }),
});

conversion.for('dataDowncast').attributeToElement({
model: 'ibexaLinkSiteaccess',
view: (siteaccess, { writer: downcastWriter }) => downcastWriter.createAttributeElement('a', { siteaccess }),
});

if (customClassesLinkConfig) {
conversion.for('editingDowncast').attributeToElement({
model: 'ibexaLinkClasses',
Expand Down Expand Up @@ -77,13 +87,16 @@ class IbexaCustomTagEditing extends Plugin {
const ibexaLinkHref = data.viewItem.getAttribute('href');
const ibexaLinkTitle = data.viewItem.getAttribute('title');
const ibexaLinkTarget = data.viewItem.getAttribute('target');
const ibexaLinkSiteaccess = data.viewItem.getAttribute('siteaccess');

const classes = data.viewItem.getAttribute('class');

conversionApi.writer.setAttributes(
{
ibexaLinkHref,
ibexaLinkTitle,
ibexaLinkTarget,
ibexaLinkSiteaccess,
},
data.modelRange,
);
Expand Down Expand Up @@ -115,6 +128,7 @@ class IbexaCustomTagEditing extends Plugin {
this.editor.model.schema.extend('$text', { allowAttributes: 'ibexaLinkHref' });
this.editor.model.schema.extend('$text', { allowAttributes: 'ibexaLinkTitle' });
this.editor.model.schema.extend('$text', { allowAttributes: 'ibexaLinkTarget' });
this.editor.model.schema.extend('$text', { allowAttributes: 'ibexaLinkSiteaccess' });

if (customAttributesLinkConfig) {
const attributes = Object.keys(customAttributesLinkConfig);
Expand Down
8 changes: 5 additions & 3 deletions src/bundle/Resources/public/js/CKEditor/link/link-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class IbexaLinkUI extends Plugin {
const formView = new IbexaLinkFormView({ locale: this.editor.locale, editor: this.editor });

this.listenTo(formView, 'save-link', () => {
const { url, title, target, ibexaLinkClasses, ibexaLinkAttributes } = this.formView.getValues();
const { url, title, target, ibexaLinkClasses, ibexaLinkAttributes, siteaccess } = this.formView.getValues();
const { path: firstPosition } = this.editor.model.document.selection.getFirstPosition();
const { path: lastPosition } = this.editor.model.document.selection.getLastPosition();
const noRangeSelection = firstPosition[0] === lastPosition[0] && firstPosition[1] === lastPosition[1];
Expand All @@ -59,7 +59,7 @@ class IbexaLinkUI extends Plugin {

this.isNew = false;

this.editor.execute('insertIbexaLink', { href: url, title, target, ibexaLinkClasses, ibexaLinkAttributes });
this.editor.execute('insertIbexaLink', { href: url, title, target, siteaccess, ibexaLinkClasses, ibexaLinkAttributes });
this.hideForm();
});

Expand All @@ -78,6 +78,7 @@ class IbexaLinkUI extends Plugin {
writer.removeAttribute('ibexaLinkHref', element);
writer.removeAttribute('ibexaLinkTitle', element);
writer.removeAttribute('ibexaLinkTarget', element);
writer.removeAttribute('ibexaLinkSiteaccess', element);

if (customClassesLinkConfig) {
writer.removeAttribute('ibexaLinkClasses', element);
Expand Down Expand Up @@ -121,6 +122,7 @@ class IbexaLinkUI extends Plugin {
url: link?.getAttribute('href') ?? '',
title: link?.getAttribute('title') ?? '',
target: link?.getAttribute('target') ?? '',
siteaccess: link?.getAttribute('siteaccess') ?? '',
};

if (customClassesLinkConfig) {
Expand Down Expand Up @@ -172,7 +174,7 @@ class IbexaLinkUI extends Plugin {

if (!link) {
this.editor.focus();
this.editor.execute('insertIbexaLink', { href: '', title: '', target: '' });
this.editor.execute('insertIbexaLink', { href: '', title: '', target: '', siteaccess: '' });

this.isNew = true;
}
Expand Down
58 changes: 53 additions & 5 deletions src/bundle/Resources/public/js/CKEditor/link/ui/link-form-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import { addMultivalueSupport } from '../../common/multivalue-dropdown/utils';
import { getCustomAttributesConfig, getCustomClassesConfig } from '../../custom-attributes/helpers/config-helper';

const { ibexa } = window;

Check warning on line 16 in src/bundle/Resources/public/js/CKEditor/link/ui/link-form-view.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=ibexa_fieldtype-richtext&issues=AZqmnstCGu0jsrLNi0rA&open=AZqmnstCGu0jsrLNi0rA&pullRequest=267

class IbexaLinkFormView extends View {
constructor(props) {
super(props);
Expand All @@ -27,6 +29,7 @@
this.urlInputView = this.createTextInput({ label: 'Link to' });
this.titleView = this.createTextInput({ label: 'Title' });
this.targetSwitcherView = this.createBoolean({ label: 'Open in tab' });
this.siteAccessView = this.createDropdown({ label: 'Site access', choices: [] });
this.attributeRenderMethods = {
string: this.createTextInput,
number: this.createNumberInput,
Expand Down Expand Up @@ -128,9 +131,10 @@
this.listenTo(this.selectContentButtonView, 'execute', this.chooseContent);
}

setValues({ url, title, target, ibexaLinkClasses, ibexaLinkAttributes = {} }) {
setValues({ url, title, target, siteaccess, ibexaLinkClasses, ibexaLinkAttributes = {} }) {
this.setStringValue(this.urlInputView, url);
this.setStringValue(this.titleView, title);
this.setChoiceValue(this.siteAccessView, siteaccess);

this.targetSwitcherView.fieldView.element.value = !!target;
this.targetSwitcherView.fieldView.set('value', !!target);
Expand All @@ -141,6 +145,12 @@
this.setChoiceValue(this.classesView, ibexaLinkClasses);
}

if (url.includes('ezlocation://')) {
const locationId = url.replace('ezlocation://', '');

this.fetchSiteaccesses(locationId);
}

Object.entries(ibexaLinkAttributes).forEach(([name, value]) => {
const attributeView = this.attributeViews[`ibexaLink${name}`];
const setValueMethod = this.setValueMethods[this.customAttributes[name].type];
Expand Down Expand Up @@ -187,6 +197,7 @@
url,
title: this.titleView.fieldView.element.value,
target: this.targetSwitcherView.fieldView.isOn ? '_blank' : '',
siteaccess: this.siteAccessView.fieldView.element.value,
};
const customClassesValue = this.classesView?.fieldView.element.value;
const customAttributesValue = Object.entries(this.attributeViews).reduce((output, [name, view]) => {
Expand Down Expand Up @@ -264,19 +275,17 @@

children.add(this.selectContentButtonView);
children.add(this.urlInputView);
children.add(this.siteAccessView);
children.add(this.titleView);
children.add(this.targetSwitcherView);

return children;
}

createDropdown(config, isCustomAttribute = false) {
createDropdownItemsList(config) {
const Translator = getTranslator();
const labeledDropdown = new LabeledFieldView(this.locale, createLabeledDropdown);
const itemsList = new Collection();

labeledDropdown.label = config.label;

if (!config.multiple && !config.required) {
itemsList.add({
type: 'button',
Expand All @@ -299,6 +308,15 @@
});
});

return itemsList;
}

createDropdown(config, isCustomAttribute = false) {
const labeledDropdown = new LabeledFieldView(this.locale, createLabeledDropdown);
const itemsList = this.createDropdownItemsList(config);

labeledDropdown.label = config.label;

addListToDropdown(labeledDropdown.fieldView, itemsList);

if (config.multiple) {
Expand Down Expand Up @@ -463,12 +481,42 @@
this.urlInputView.fieldView.set('value', url);
this.urlInputView.fieldView.set('isEmpty', !url);

this.fetchSiteaccesses(items[0].id);

this.editor.focus();
}

cancelHandler() {
this.editor.focus();
}

fetchSiteaccesses(locationId) {
const request = new Request(`/api/ibexa/v2/site-access/by-location/${locationId}?resolver_type=non_admin`, {
method: 'GET',
headers: {
Accept: 'application/json',
},
mode: 'same-origin',
credentials: 'same-origin',
});

fetch(request)
.then(ibexa.helpers.request.getJsonFromResponse)
.then((response) => {
const itemsList = this.createDropdownItemsList({
choices: response.SiteAccessesList.values.map((siteaccess) => siteaccess.name),
});

this.siteAccessView.fieldView.once(
'change:isOpen',
() => {
this.siteAccessView.fieldView.panelView.children.clear();
addListToDropdown(this.siteAccessView.fieldView, itemsList);
},
{ priority: 'highest' },
);
});
}
}

export default IbexaLinkFormView;
1 change: 0 additions & 1 deletion src/bundle/Resources/public/scss/_balloon-form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
border: calculateRem(1px) solid $ibexa-color-dark-200;
border-radius: calculateRem(5px);
width: 100%;
max-width: calculateRem(288px);

.ibexa-ckeditor-dropdown-selected-items {
display: flex;
Expand Down
13 changes: 13 additions & 0 deletions src/bundle/Resources/richtext/schemas/docbook/docbook.rng
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,13 @@
<ref name="db.xlink.show.enumeration"/>
</attribute>
</define>
<define name="db.xlink.siteaccess.attribute">
<optional>
<attribute name="xlink:siteaccess">
<a:documentation>Specifies the siteaccess for the location</a:documentation>
</attribute>
</optional>
</define>
<define name="db.xlink.actuate.enumeration">
<choice>
<value>onLoad</value>
Expand Down Expand Up @@ -291,6 +298,9 @@
<optional>
<ref name="db.xlink.actuate.attribute"/>
</optional>
<optional>
<ref name="db.xlink.siteaccess.attribute"/>
</optional>
</interleave>
</define>
<define name="db.xml.id.attribute">
Expand Down Expand Up @@ -6878,6 +6888,9 @@ O, the molecular formula for water)</a:documentation>
<optional>
<ref name="db.xlink.to.attribute"/>
</optional>
<optional>
<ref name="db.xlink.siteaccess.attribute"/>
</optional>
</interleave>
</define>
<define name="db.arc">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@
<xsl:value-of select="@xlink:title"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@xlink:siteaccess">
<xsl:attribute name="siteaccess">
<xsl:value-of select="@xlink:siteaccess"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@ezxhtml:class">
<xsl:attribute name="class">
<xsl:value-of select="@ezxhtml:class"/>
Expand Down Expand Up @@ -660,6 +665,11 @@
<xsl:value-of select="@xlink:title"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@xlink:siteaccess">
<xsl:attribute name="siteaccess">
<xsl:value-of select="@xlink:siteaccess"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@ezxhtml:class">
<xsl:attribute name="class">
<xsl:value-of select="@ezxhtml:class"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@
<xsl:value-of select="@xlink:title"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="not(normalize-space(@xlink:siteaccess) = '')">
<xsl:attribute name="siteaccess">
<xsl:value-of select="@xlink:siteaccess"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@ezxhtml:class">
<xsl:attribute name="class">
<xsl:value-of select="@ezxhtml:class"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@
<xsl:value-of select="@title"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@siteaccess">
<xsl:attribute name="xlink:siteaccess">
<xsl:value-of select="@siteaccess"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@class">
<xsl:attribute name="ezxhtml:class">
<xsl:value-of select="@class"/>
Expand Down
Loading
Loading