Multiple controllers in an extension - typo3

Is it actually possible to write an extension with multiple controllers that will work automatically on all sites? What i want is an extension that would call controller A when site A is opened, controller B when site B is opened and so on.
I saw here https://docs.typo3.org/typo3cms/extensions/news/ that multiple controllers is possible with FlexForms and switchableControllerActions. The thing is, when i add the plugin to the site, i have to specify which controller should work for this site. I want the configuration directly in the extension and not from typo3 backend.
I know i can use the page id and call the function based on it but i'm trying to avoid it and search for better solution.

Sure this is possible. You need to use FlexForms here which is basically XML based field in your tt_content record. Thus you can configer your plugin directly your content record. Typically used for setting limit to records, sorting, etc. But also for setting any allowed controller->action combination, where the first one is default. Just have a look at some of the well know extensions how they use it.
Here is a little abstract fore the relavant part of the FlexForm:
<switchableControllerActions>
<TCEforms>
<label>LLL:EXT:ra_registration/Resources/Private/Language/locallang_be.xml:flexforms_general.mode</label>
<config>
<type>select</type>
<items>
<numIndex index="0">
<numIndex index="0">LLL:EXT:ra_registration/Resources/Private/Language/locallang_be.xml:flexforms_general.mode.registration_index</numIndex>
<numIndex index="1">Registration->index;Registration->register;User->new;User->create;User->confirm;User->index;User->remind</numIndex>
</numIndex>
<numIndex index="1">
<numIndex index="0">LLL:EXT:ra_registration/Resources/Private/Language/locallang_be.xml:flexforms_general.mode.registration_reminder</numIndex>
<numIndex index="1">User->index;User->remind;User->remindConfirm</numIndex>
</numIndex>
</items>
</config>
</TCEforms>
</switchableControllerActions>
As said you can define any controller / action combination such as
MyProduct->index
or
MyCustomer->list
etc.
In order use the FlexForm you need to register it in the ext_tables.php
$TCA['tt_content']['types']['list']['subtypes_addlist'][$pluginSignature] = 'pi_flexform';
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue('myextenion_pi1', 'FILE:EXT:' . $_EXTKEY . '/Configuration/FlexForms/setup.xml');

Related

Inconsistency between documented guidelines and project templates

When I look at the Developer Guide on the SAPUI5 website this is how they declare an XML view:
<mvc:View
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc" controllerName="">
</mvc:View>
And a controller is defined like this:
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function (Controller) {
"use strict";
return Controller.extend("", {
});
});
However, when I create an SAPUI5 project in Eclipse and use the option New > SAPUI5 Application Development > View, it creates a view and a controller that look like this:
<core:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
controllerName="" xmlns:html="http://www.w3.org/1999/xhtml">
</core:View>
sap.ui.controller("", {
});
On one hand, creating a view in the above manner saves me from typing the basic syntax every time. Yet on the other hand, the syntax in the developer guide (especially the controller) looks more organized to the eye.
Is there a particular reason why I should use one or the other syntax? Or can I use either approach without any difference in programming?
I am using v1.32 for development.
The first syntax (sap.ui.define) is the preferred syntax. It is also known as AMD (Async Module Declaration) syntax (see this Wiki article for more information). It wraps the module (a controller in your case) in a function call which enables
clear and easy to read declaration of the module
asynchronous invocation of the module (once all dependencies are loaded)
One library that implements this syntax is RequireJS, which is also embedded into SAPUI5 (and OpenUI5 ofc).
In their documentation about control libraries, the SAPUI5 team also recommends the AMD syntax (see here). All controls in the sap.m and sap.ui package (that I've checked) use the AMD syntax.
You can also read this interesting blog post from DJ Adams.
However it is nowhere stated (afaik) that the second syntax is deprecated. But keep in mind that it's auto generated by Eclipse because it (the UI5 plugin) is rarely maintained and therefore not up to date (they prefer developing with Node.js + grunt + Sublime/Visual Studio Code/etc.).
There you can get shorter paths for your dependencies by doing var Controller = sap.ui.core.mvc.Controller (after you required the module)
For the syntax of the view, it'll help if you understand it.
To declare an XML namespace, you need to use the following syntax :
xmlns:<namespace>="<library the namespace refers to>"
The goal of the namespace is to provide an easy and convenient way of referring to a specific library without typing out its name. In this case :
<mvc:View
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc" controllerName="">
</mvc:View>
the mvc:View component refers to the View class of the sap.ui.core.mvc library. mvc:View is the equivalent of sap.ui.core.mvc.View. You can name your namespace however you want.
The very first thing you declare in your XML view is the container for your view. This is the component which will contain all the other components of the view - the root component of the view. You can use components of different libraries as containers for your view. In this example, you are using the View component of your sap.ui.core.mvc library. In the following example:
<core:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
controllerName="" xmlns:html="http://www.w3.org/1999/xhtml">
</core:View>
You are using the View component of your sap.ui.core library.
The following line:
xmlns="sap.m"
indicates the default library. This is the library referred to by components declared without a namespace. If later on in my view, I declare the following component:
<Input id="myinput"></Input>
The UI5 library will load the Input class from the default library, here sap.m.
Essentially, there is only one syntax for an XML view:
<myNamespace:myContainerComponent
xmlns="<my.default.library>"
xmlns:<myFirstNamespace>="my.namespace.library"
<!-- more if needed -->
controllerName="my.controller.name">
<!-- All your other components -->
</myNamespace:myContainerComponent>
I do not know enough about the possible controller syntaxes to be able to explain them. I will let someone more knowledgeable than I explain those further.
Hope this helps and makes things clearer for you.
<core:View ...> is simply wrong. Instead, write <mvc:View xmlns:mvc="sap.ui.core.mvc" ...>. For more information, see the replies and links from this GitHub issue "View class doesn't exist in the 'sap.ui.core' namespace".
sap.ui.controller is a deprecated API. The replacement is mentioned in the linked method description.
Templates / generators can be outdated too and thus, unfortunately, don't always follow best practices. No matter which tool or IDE you use to generate code, please double-check with the documented guidelines.

Add custom properties to eclipse's project class

I have a custom project nature and created a new project that has this new custom nature.
What I am trying to do now, is extend the properties of that project, so when it is selected e.g. in package explorer view, not only the standard project properties are shown in the (standard) property-view but also customized ones (like the nature of the selected project - but only for a project that has my custom nature)
Is this possible with standard eclipse extension points?
I have doubts since I don't have my own class where I could register a property-descriptor, just a new nature.
You should be able to define a project properties page without a project class, as I've done in the Haskell plugin:
<page
name="%projectFlagsPP_name"
class="net.sf.eclipsefp.haskell.ui.properties.UserFlagsPP"
id="net.sf.eclipsefp.haskell.ui.properties.UserFlagsPP">
<filter
name="nature"
value="net.sf.eclipsefp.haskell.core.project.HaskellNature">
</filter>
<filter
name="open"
value="true">
</filter>
<enabledWhen>
<adapt type="org.eclipse.core.resources.IProject" />
</enabledWhen>
</page>
And then the java code starts like:
public class UserFlagsPP extends PropertyPage implements
IWorkbenchPreferencePage {
This says that the property page will appear for a IProject that has the Haskell Nature...

Extend Teamsite actions

I was wondering if it possible to extend Teamsite functionality? For example, I would like to add my own button under Actions -> MyAction which would perform my java based operation (update pages or something)?
For custom menu actions you'll need to make modifications to
<iw-home>/local/config/lib/content_center/customer_src/etc/conf/customer/ui_custom.xml
There should be some examples in the file unless you've erased the contents. The basic format is as follows:
<action-list id="iw.ccpro.filesys.menubar">
<menu id="iw.ccpro.action.menu">
<link id="company.ccpro.list_directory.custMenuAction.link"
label="Custom Action"
description="Custom Action Description"
url="/iw-bin/custom_menu_action.ipl"
target="_blank"
icon="/base/images/customIcon.gif"
/>
</menu>
</action-list>
For a Java based operation you would just change the url to your servlet path.
For example:
url="<iw-hostname>/iw-cc/command/customJavaAction"

CQ5: Inheriting/Extended Dialogs

For reference, I'm on CQ5.5
I am curious if there is any way to extend upon an inherited dialog, without overwriting it's parent dialog.
For example, have a structure as follows:
base-page-template
- dialog
- title
- description
inerited-from-base-page
- dialog
- custom field
--------------- [inherited from parent]
- title
- description
What I'm trying to avoid is for example: I need to add a new property to base-page that should show up on all page templates that extend from base-page. My current solution is to add that property to all dialogs separately. So for example, in the above structure I would have to add the new "default property" to both the base-page and the inherited-from-base-page dialogs.
The only other option I could think of was creating a panel node that represents "base page" and then including that panel w/ an xtype:cqinclude node.
Before going with the latter route I'm curious if anyone has extended their dialogs in the fashion I'm describing above.
Any help is greatly appreciated, Thank you,
Brodie
No, there is no way to directly inherit dialogs. The best you can do is to include the dialog tabs using path property.
You should create your tab your tabs in a different location and you can include it in your dialog using path property like shown below:
<items jcr:primaryType="cq:WidgetCollection">
<tabs jcr:primaryType="cq:TabPanel">
<items jcr:primaryType="cq:WidgetCollection">
<tab1
jcr:primaryType="cq:Widget"
path="/apps/myproject/tab1.infinity.json"
xtype="cqinclude"/>
<tab2
jcr:primaryType="cq:Widget"
path="/apps/myproject/tab2.infinity.json"
xtype="cqinclude"/>
</items>
</tabs>
</items>
Where tab1 and tab2 are tab panels.
So, in your case it will be something like this :
base_page_dialog_tab
- dialog
- title
- description
inherited page-dialog-tab
- custom field
base-page-template
- include base page dialog tab here.
inerited-from-base-page
- include Tab 1 - inherited page-dialog tab using path property
- include Tab 2 - base page dialog tab using path property.
The above answer provided by Rajesh is correct w.r.t to dialog.xml written for classic UI interface in AEM.
The touch UI equivalent of cqinclude is sling:resourceType="granite/ui/components/foundation/include".
Example:
<basic
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/include"
path="foundation/components/page/cq:dialog/content/items/tabs/items/basic"/>
With touch UI in AEM, A different kind of dialog inheritance is possible using the sling:resourceSuperType property, however please note that this does not inherit dialog properties from its live copy parent. The dialog is inherited from its sling resource super-type.
I understand that this feature is not a solution to the problem described above, Just wanted to point out that dialog inheritance is possible with the new TOUCH-UI authoring.
Following is an example.
base_page_dialog_tab (sling:resourceType='A')
- dialog
- title
- description
page-dialog-tab (sling:resourceSuperType=sling:resourceSuperType='A')
- custom field
In the above example, the page-dialog-tab would have the following four properties in its dialog.
- dialog
- title
- description
- custom field
A few useful config options available like sling:hideProperties, sling:hideResource, sling:hideChildren and sling:orderBefore to hide and order properties in the dialog.

Removing a view from Eclipse Window -> Show views

We have an application in which some views only work when attached to certain perspectives.
We want to remove those views from the Window -> Show View dialog so that users cannot add them to perspectives where they don't work.
Any ideas on how to do this either programmatically or declaratively?
I have tried using <visibleWhen />, but the views are still showing in the dialog:
<view class="com.mycompany.ViewClass"
id="com.mycompany.ViewId"
name="View Name"
restorable="true">
<visibleWhen>
<with variable="activeWorkbenchWindow.activePerspective">
<equals value="com.mycompany.MyPerspective"/>
</with>
</visibleWhen>
</view>
I don't think there is any problem with the <visibleWhen /> clause, so I'm wondering if it can be used with a View?
It should be treated as a menu contribution, using the <visibleWhen/> to only display that option when a certain condition is met.
See the wiki article "Menu Contribution" for more.
Unfortunately, it seems that Eclipse already does this for the Introduction view by calling the private ViewContentProvider.removeIntroView on the content provider for the Show Views dialog. A way to get around this limitation is to define activities by adding to the org.eclipse.ui.activities extension point (see activityPatternBinding on how activities can be mapped to UI contributions). Doing this will not only remove the views from the Show Views dialog, but it will also prevent them from showing in the perspectives themselves. The views can then be shown programmatically. I had to also enable the activities in the ApplicationWorkbenchAdvisor.preStartup method because of limitations in our application:
Set<String> activityIds = new HashSet<String>();
activityIds.add("com.my.activity.id");
IWorkbenchActivitySupport activitySupport = PlatformUI.getWorkbench().getActivitySupport();
activitySupport.setEnabledActivityIds(activityIds);
In this case, the activity has to be disabled before showing the dialog, so the Show Views menu contribution has to be modified to do this as well.
Hopefully an extension point will be added to the next version of Eclipse to provide the option for developers to remove views from the dialog declaratively.